Sync.cpp revision fd54266907c3046339b48748f63afa32ee3ab4e1
1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16581bed77d3596b9d7242da10867c8d4cfd382239Andy McFadden
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Fundamental synchronization mechanisms.
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The top part of the file has operations on "monitor" structs; the
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * next part has the native calls on objects.
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The current implementation uses "thin locking" to avoid allocating
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an Object's full Monitor struct until absolutely necessary (i.e.,
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * during contention or a call to wait()).
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: make improvements to thin locking
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We may be able to improve performance and reduce memory requirements by:
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  - reverting to a thin lock once the Monitor is no longer necessary
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  - using a pool of monitor objects, with some sort of recycling scheme
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: recycle native-level monitors when objects are garbage collected.
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h"
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h>
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <unistd.h>
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <pthread.h>
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <time.h>
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <sys/time.h>
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <errno.h>
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define LOG_THIN    LOGV
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION     /* fwd */
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic const char* kStartBanner =
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#";
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic const char* kEndBanner =
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#->";
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unsorted, expanding list of objects.
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is very similar to PointerSet (which came into existence after this),
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * but these are unsorted, uniqueness is not enforced by the "add" function,
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and the base object isn't allocated on the heap.
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct ExpandingObjectList {
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u2          alloc;
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u2          count;
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object**    list;
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} ExpandingObjectList;
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* fwd */
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void updateDeadlockPrediction(Thread* self, Object* obj);
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void removeCollectedObject(Object* obj);
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void expandObjClear(ExpandingObjectList* pList);
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Every Object has a monitor associated with it, but not every Object is
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * actually locked.  Even the ones that are locked do not need a
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * full-fledged monitor until a) there is actual contention or b) wait()
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is called on the Object.
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For Dalvik, we have implemented a scheme similar to the one described
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in Bacon et al.'s "Thin locks: featherweight synchronization for Java"
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (ACM 1998).  Things are even easier for us, though, because we have
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a full 32 bits to work with.
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8194338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * The two states of an Object's lock are referred to as "thin" and
8294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * "fat".  A lock may transition from the "thin" state to the "fat"
8394338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * state and this transition is referred to as inflation.  Once a lock
8494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * has been inflated it remains in the "fat" state indefinitely.
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * The lock value itself is stored in Object.lock.  The LSB of the
8777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * lock encodes its state.  When cleared, the lock is in the "thin"
8877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * state and its bits are formatted as follows:
8971938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro *
9094338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro *    [31 ---- 19] [18 ---- 3] [2 ---- 1] [0]
9194338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro *     lock count   thread id  hash state  0
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
9377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * When set, the lock is in the "fat" state and its bits are formatted
9494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * as follows:
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
9694338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro *    [31 ---- 3] [2 ---- 1] [0]
9794338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro *      pointer   hash state  1
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For an in-depth description of the mechanics of thin-vs-fat locking,
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * read the paper referred to above.
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Monitors provide:
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  - mutually exclusive access to resources
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  - a way for multiple threads to wait for notification
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In effect, they fill the role of both mutexes and condition variables.
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Only one thread can own the monitor at any time.  There may be several
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * threads waiting on it (the wait call unlocks it).  One or more waiting
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * threads may be getting interrupted or notified at any given time.
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstruct Monitor {
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread*     owner;          /* which thread currently owns the lock? */
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int         lockCount;      /* owner's recursive lock depth */
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object*     obj;            /* what object are we part of [debug only] */
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
11977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    Thread*     waitSet;	/* threads currently waiting on this monitor */
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pthread_mutex_t lock;
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor*    next;
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Objects that have been locked immediately after this one in the
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * past.  We use an expanding flat array, allocated on first use, to
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * minimize allocations.  Deletions from the list, expected to be
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * infrequent, are crunched down.
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExpandingObjectList historyChildren;
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We also track parents.  This isn't strictly necessary, but it makes
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the cleanup at GC time significantly faster.
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExpandingObjectList historyParents;
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* used during cycle detection */
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool        historyMark;
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* stack trace, established the first time we locked the object */
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int         historyStackDepth;
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int*        historyRawStackTrace;
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project};
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create and initialize a monitor.
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectMonitor* dvmCreateMonitor(Object* obj)
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon;
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon = (Monitor*) calloc(1, sizeof(Monitor));
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon == NULL) {
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("Unable to allocate monitor\n");
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAbort();
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
16294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    if (((u4)mon & 7) != 0) {
16394338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        LOGE("Misaligned monitor: %p\n", mon);
16494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        dvmAbort();
16594338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    }
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->obj = obj;
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmInitMutex(&mon->lock);
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* replace the head of the list with the new monitor */
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    do {
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon->next = gDvm.monitorList;
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } while (!ATOMIC_CMP_SWAP((int32_t*)(void*)&gDvm.monitorList,
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                              (int32_t)mon->next, (int32_t)mon));
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return mon;
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free the monitor list.  Only used when shutting the VM down.
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmFreeMonitorList(void)
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon;
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* nextMon;
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon = gDvm.monitorList;
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (mon != NULL) {
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        nextMon = mon->next;
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        expandObjClear(&mon->historyChildren);
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        expandObjClear(&mon->historyParents);
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(mon->historyRawStackTrace);
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(mon);
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon = nextMon;
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Log some info about our monitors.
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpMonitorInfo(const char* msg)
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if QUIET_ZYGOTE_MONITOR
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.zygote) {
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int totalCount;
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int liveCount;
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    totalCount = liveCount = 0;
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon = gDvm.monitorList;
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (mon != NULL) {
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        totalCount++;
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (mon->obj != NULL)
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            liveCount++;
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon = mon->next;
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGD("%s: monitor list has %d entries (%d live)\n",
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        msg, totalCount, liveCount);
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the object that a monitor is part of.
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectObject* dvmGetMonitorObject(Monitor* mon)
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon == NULL)
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return mon->obj;
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
23930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * Returns the thread id of the thread owning the given lock.
24030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */
24130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapirostatic u4 lockOwner(Object* obj)
24230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro{
24330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    Thread *owner;
24430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    u4 lock;
24530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro
24630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    assert(obj != NULL);
24730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    /*
24830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro     * Since we're reading the lock value multiple times, latch it so
24930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro     * that it doesn't change out from under us if we get preempted.
25030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro     */
25130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    lock = obj->lock;
25230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    if (LW_SHAPE(lock) == LW_SHAPE_THIN) {
25330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        return LW_LOCK_OWNER(lock);
25430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    } else {
25530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        owner = LW_MONITOR(lock)->owner;
25630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        return owner ? owner->threadId : 0;
25730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    }
25830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro}
25930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro
26030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro/*
261fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * Get the thread that holds the lock on the specified object.  The
262fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * object may be unlocked, thin-locked, or fat-locked.
263fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden *
264fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * The caller must lock the thread list before calling here.
265fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden */
266fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFaddenThread* dvmGetObjectLockHolder(Object* obj)
267fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden{
268fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    u4 threadId = lockOwner(obj);
269fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden
270fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    if (threadId == 0)
271fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden        return NULL;
272fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    return dvmGetThreadByThreadId(threadId);
273fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden}
274fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden
275fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden/*
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Checks whether the given thread holds the given
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * objects's lock.
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmHoldsLock(Thread* thread, Object* obj)
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (thread == NULL || obj == NULL) {
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
28430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        return thread->threadId == lockOwner(obj);
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free the monitor associated with an object and make the object's lock
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * thin again.  This is called during garbage collection.
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2925a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapirostatic void freeObjectMonitor(Object* obj)
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor *mon;
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2965a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    assert(LW_SHAPE(obj->lock) == LW_SHAPE_FAT);
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.deadlockPredictMode != kDPOff)
3005a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro        removeCollectedObject(obj);
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3035a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    mon = LW_MONITOR(obj->lock);
3045a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    obj->lock = DVM_LOCK_INITIAL_THIN_VALUE;
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* This lock is associated with an object
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that's being swept.  The only possible way
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * anyone could be holding this lock would be
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * if some JNI code locked but didn't unlock
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the object, in which case we've got some bad
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * native code somewhere.
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(pthread_mutex_trylock(&mon->lock) == 0);
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pthread_mutex_destroy(&mon->lock);
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
3165a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    expandObjClear(&mon->historyChildren);
3175a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    expandObjClear(&mon->historyParents);
3185a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    free(mon->historyRawStackTrace);
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
3205a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    free(mon);
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3235a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro/*
3245a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro * Frees monitor objects belonging to unmarked objects.
3255a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro */
3265a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapirovoid dvmSweepMonitorList(Monitor** mon, int (*isUnmarkedObject)(void*))
3275a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro{
3285a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    Monitor handle;
3295a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    Monitor *prev, *curr;
3305a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    Object *obj;
3315a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro
3325a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    assert(mon != NULL);
3335a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    assert(isUnmarkedObject != NULL);
3345a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    prev = &handle;
3355a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    prev->next = curr = *mon;
3365a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    while (curr != NULL) {
3375a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro        obj = curr->obj;
3385a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro        if (obj != NULL && (*isUnmarkedObject)(obj) != 0) {
3395a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro            prev->next = curr = curr->next;
3405a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro            freeObjectMonitor(obj);
3415a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro        } else {
3425a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro            prev = curr;
3435a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro            curr = curr->next;
3445a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro        }
3455a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    }
3465a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    *mon = handle.next;
3475a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro}
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Lock a monitor.
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void lockMonitor(Thread* self, Monitor* mon)
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int cc;
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon->owner == self) {
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon->lockCount++;
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ThreadStatus oldStatus;
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pthread_mutex_trylock(&mon->lock) != 0) {
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* mutex is locked, switch to wait status and sleep on it */
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            oldStatus = dvmChangeStatus(self, THREAD_MONITOR);
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cc = pthread_mutex_lock(&mon->lock);
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(cc == 0);
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmChangeStatus(self, oldStatus);
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon->owner = self;
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(mon->lockCount == 0);
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Try to lock a monitor.
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" on success.
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool tryLockMonitor(Thread* self, Monitor* mon)
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int cc;
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon->owner == self) {
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon->lockCount++;
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cc = pthread_mutex_trylock(&mon->lock);
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (cc == 0) {
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mon->owner = self;
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(mon->lockCount == 0);
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unlock a monitor.
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns true if the unlock succeeded.
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the unlock failed, an exception will be pending.
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool unlockMonitor(Thread* self, Monitor* mon)
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
40777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(self != NULL);
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(mon != NULL);        // can this happen?
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon->owner == self) {
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We own the monitor, so nobody else can be in here.
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (mon->lockCount == 0) {
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int cc;
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mon->owner = NULL;
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cc = pthread_mutex_unlock(&mon->lock);
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(cc == 0);
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mon->lockCount--;
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We don't own this, so we're not allowed to unlock it.
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The JNI spec says that we should throw IllegalMonitorStateException
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * in this case.
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
4289111757cc56570eae183ccf6e1c311a79ee3127bCarl Shapiro        dvmThrowExceptionFmt("Ljava/lang/IllegalMonitorStateException;",
4299111757cc56570eae183ccf6e1c311a79ee3127bCarl Shapiro                             "unlock of unowned monitor, self=%d owner=%d",
4309111757cc56570eae183ccf6e1c311a79ee3127bCarl Shapiro                             self->threadId,
4319111757cc56570eae183ccf6e1c311a79ee3127bCarl Shapiro                             mon->owner ? mon->owner->threadId : 0);
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
43877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * Checks the wait set for circular structure.  Returns 0 if the list
439b453919fee9bf10ccd576d389d8b3584061bba8bCarl Shapiro * is not circular.  Otherwise, returns 1.  Used only by asserts.
44077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro */
44177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapirostatic int waitSetCheck(Monitor *mon)
44277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro{
44377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    Thread *fast, *slow;
44477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    size_t n;
44577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
44677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(mon != NULL);
44777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    fast = slow = mon->waitSet;
44877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    n = 0;
44977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    for (;;) {
45077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        if (fast == NULL) return 0;
45177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        if (fast->waitNext == NULL) return 0;
4525f56e67999c67861872c27097803d2126142fed4Carl Shapiro        if (fast == slow && n > 0) return 1;
45377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        n += 2;
45477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        fast = fast->waitNext->waitNext;
45577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        slow = slow->waitNext;
45677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
45777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro}
45877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
45977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro/*
46030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * Links a thread into a monitor's wait set.  The monitor lock must be
46130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * held by the caller of this routine.
46277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro */
46377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapirostatic void waitSetAppend(Monitor *mon, Thread *thread)
46477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro{
46577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    Thread *elt;
46677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
46777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(mon != NULL);
46830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    assert(mon->owner == dvmThreadSelf());
46977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(thread != NULL);
47077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(thread->waitNext == NULL);
47177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(waitSetCheck(mon) == 0);
47277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (mon->waitSet == NULL) {
47377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        mon->waitSet = thread;
47477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        return;
47577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
47677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    elt = mon->waitSet;
47777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    while (elt->waitNext != NULL) {
47877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        elt = elt->waitNext;
47977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
48077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    elt->waitNext = thread;
48177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro}
48277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
48377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro/*
48430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * Unlinks a thread from a monitor's wait set.  The monitor lock must
48530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * be held by the caller of this routine.
48677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro */
48777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapirostatic void waitSetRemove(Monitor *mon, Thread *thread)
48877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro{
48977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    Thread *elt;
49077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
49177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(mon != NULL);
49230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    assert(mon->owner == dvmThreadSelf());
49377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(thread != NULL);
49477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(waitSetCheck(mon) == 0);
49577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (mon->waitSet == NULL) {
49677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        return;
49777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
49877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (mon->waitSet == thread) {
49977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        mon->waitSet = thread->waitNext;
50077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        thread->waitNext = NULL;
50177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        return;
50277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
50377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    elt = mon->waitSet;
50477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    while (elt->waitNext != NULL) {
50577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        if (elt->waitNext == thread) {
50677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro            elt->waitNext = thread->waitNext;
50777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro            thread->waitNext = NULL;
50877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro            return;
50977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        }
51077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        elt = elt->waitNext;
51177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
51277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro}
51377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
514b453919fee9bf10ccd576d389d8b3584061bba8bCarl Shapiro/*
515b453919fee9bf10ccd576d389d8b3584061bba8bCarl Shapiro * Converts the given relative waiting time into an absolute time.
516b453919fee9bf10ccd576d389d8b3584061bba8bCarl Shapiro */
517fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbeevoid absoluteTime(s8 msec, s4 nsec, struct timespec *ts)
51877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro{
51977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    s8 endSec;
52077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
52177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro#ifdef HAVE_TIMEDWAIT_MONOTONIC
52277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    clock_gettime(CLOCK_MONOTONIC, ts);
52377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro#else
52477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    {
52577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        struct timeval tv;
52677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        gettimeofday(&tv, NULL);
52777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        ts->tv_sec = tv.tv_sec;
52877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        ts->tv_nsec = tv.tv_usec * 1000;
52977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
53077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro#endif
53177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    endSec = ts->tv_sec + msec / 1000;
53277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (endSec >= 0x7fffffff) {
53377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        LOGV("NOTE: end time exceeds epoch\n");
53477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        endSec = 0x7ffffffe;
53577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
53677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    ts->tv_sec = endSec;
53777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    ts->tv_nsec = (ts->tv_nsec + (msec % 1000) * 1000000) + nsec;
53877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
53977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    /* catch rollover */
54077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (ts->tv_nsec >= 1000000000L) {
54177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        ts->tv_sec++;
54277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        ts->tv_nsec -= 1000000000L;
54377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
54477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro}
54577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
546fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbeeint dvmRelativeCondWait(pthread_cond_t* cond, pthread_mutex_t* mutex,
547fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee                        s8 msec, s4 nsec)
548fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee{
549fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee    int ret;
550fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee    struct timespec ts;
551fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee    absoluteTime(msec, nsec, &ts);
552fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee#if defined(HAVE_TIMEDWAIT_MONOTONIC)
553fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee    ret = pthread_cond_timedwait_monotonic(cond, mutex, &ts);
554fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee#else
555fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee    ret = pthread_cond_timedwait(cond, mutex, &ts);
556fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee#endif
557fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee    assert(ret == 0 || ret == ETIMEDOUT);
558fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee    return ret;
559fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee}
560fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee
56177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro/*
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Wait on a monitor until timeout, interrupt, or notification.  Used for
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Object.wait() and (somewhat indirectly) Thread.sleep() and Thread.join().
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If another thread calls Thread.interrupt(), we throw InterruptedException
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and return immediately if one of the following are true:
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  - blocked in wait(), wait(long), or wait(long, int) methods of Object
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  - blocked in join(), join(long), or join(long, int) methods of Thread
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  - blocked in sleep(long), or sleep(long, int) methods of Thread
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Otherwise, we set the "interrupted" flag.
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Checks to make sure that "nsec" is in the range 0-999999
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (i.e. fractions of a millisecond) and throws the appropriate
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exception if it isn't.
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The spec allows "spurious wakeups", and recommends that all code using
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Object.wait() do so in a loop.  This appears to derive from concerns
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * about pthread_cond_wait() on multiprocessor systems.  Some commentary
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * on the web casts doubt on whether these can/should occur.
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Since we're allowed to wake up "early", we clamp extremely long durations
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to return at the end of the 32-bit time epoch.
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void waitMonitor(Thread* self, Monitor* mon, s8 msec, s4 nsec,
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool interruptShouldThrow)
586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct timespec ts;
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool wasInterrupted = false;
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool timed;
59077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    int ret;
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
59271938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    assert(self != NULL);
59371938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    assert(mon != NULL);
59471938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro
59594338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    /* Make sure that we hold the lock. */
59671938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    if (mon->owner != self) {
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "object not locked by thread before wait()");
599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Enforce the timeout range.
604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (msec < 0 || nsec < 0 || nsec > 999999) {
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/lang/IllegalArgumentException;",
607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "timeout arguments out of range");
608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Compute absolute wakeup time, if necessary.
613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (msec == 0 && nsec == 0) {
615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        timed = false;
616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
617fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee        absoluteTime(msec, nsec, &ts);
618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        timed = true;
619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Add ourselves to the set of threads waiting on this monitor, and
623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * release our hold.  We need to let it go even if we're a few levels
624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * deep in a recursive lock, and we need to restore that later.
625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
626142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapiro     * We append to the wait set ahead of clearing the count and owner
627142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapiro     * fields so the subroutine can check that the calling thread owns
628142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapiro     * the monitor.  Aside from that, the order of member updates is
629142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapiro     * not order sensitive as we hold the pthread mutex.
630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
631142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapiro    waitSetAppend(mon, self);
632142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapiro    int prevLockCount = mon->lockCount;
633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->lockCount = 0;
634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->owner = NULL;
635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Update thread status.  If the GC wakes up, it'll ignore us, knowing
638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that we won't touch any references in this state, and we'll check
639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * our suspend mode before we transition out.
640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (timed)
642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmChangeStatus(self, THREAD_TIMED_WAIT);
643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmChangeStatus(self, THREAD_WAIT);
645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
64677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    ret = pthread_mutex_lock(&self->waitMutex);
64777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(ret == 0);
64877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
65077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     * Set waitMonitor to the monitor object we will be waiting on.
65177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     * When waitMonitor is non-NULL a notifying or interrupting thread
65277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     * must signal the thread's waitCond to wake it up.
653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
65477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(self->waitMonitor == NULL);
655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->waitMonitor = mon;
656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Handle the case where the thread was interrupted before we called
659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * wait().
660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (self->interrupted) {
662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        wasInterrupted = true;
66377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        self->waitMonitor = NULL;
66477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        pthread_mutex_unlock(&self->waitMutex);
665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto done;
666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
66877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    /*
66977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     * Release the monitor lock and wait for a notification or
67077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     * a timeout to occur.
67177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     */
67277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    pthread_mutex_unlock(&mon->lock);
67377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
67477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (!timed) {
67577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        ret = pthread_cond_wait(&self->waitCond, &self->waitMutex);
67677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        assert(ret == 0);
67777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    } else {
678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef HAVE_TIMEDWAIT_MONOTONIC
67977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        ret = pthread_cond_timedwait_monotonic(&self->waitCond, &self->waitMutex, &ts);
680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
68177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        ret = pthread_cond_timedwait(&self->waitCond, &self->waitMutex, &ts);
682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
68377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        assert(ret == 0 || ret == ETIMEDOUT);
68477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
68577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (self->interrupted) {
68677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        wasInterrupted = true;
687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
68977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    self->interrupted = false;
69077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    self->waitMonitor = NULL;
69177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
69277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    pthread_mutex_unlock(&self->waitMutex);
69377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
69430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    /* Reacquire the monitor lock. */
69577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    lockMonitor(self, mon);
696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
697142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapirodone:
698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
69907b359273a838a15accafefcbe861be15caaac3aCarl Shapiro     * We remove our thread from wait set after restoring the count
70007b359273a838a15accafefcbe861be15caaac3aCarl Shapiro     * and owner fields so the subroutine can check that the calling
70107b359273a838a15accafefcbe861be15caaac3aCarl Shapiro     * thread owns the monitor. Aside from that, the order of member
70207b359273a838a15accafefcbe861be15caaac3aCarl Shapiro     * updates is not order sensitive as we hold the pthread mutex.
703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->owner = self;
705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->lockCount = prevLockCount;
70607b359273a838a15accafefcbe861be15caaac3aCarl Shapiro    waitSetRemove(mon, self);
707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* set self->status back to THREAD_RUNNING, and self-suspend if needed */
709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmChangeStatus(self, THREAD_RUNNING);
710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (wasInterrupted) {
712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We were interrupted while waiting, or somebody interrupted an
71430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * un-interruptible thread earlier and we're bailing out immediately.
715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The doc sayeth: "The interrupted status of the current thread is
717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * cleared when this exception is thrown."
718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        self->interrupted = false;
720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (interruptShouldThrow)
721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/InterruptedException;", NULL);
722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Notify one thread waiting on this monitor.
727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void notifyMonitor(Thread* self, Monitor* mon)
729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
73077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    Thread* thread;
73177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
73271938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    assert(self != NULL);
73371938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    assert(mon != NULL);
73471938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro
73594338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    /* Make sure that we hold the lock. */
73671938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    if (mon->owner != self) {
737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "object not locked by thread before notify()");
739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
74130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    /* Signal the first waiting thread in the wait set. */
74230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    while (mon->waitSet != NULL) {
74377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        thread = mon->waitSet;
74477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        mon->waitSet = thread->waitNext;
74577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        thread->waitNext = NULL;
74677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        pthread_mutex_lock(&thread->waitMutex);
74777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        /* Check to see if the thread is still waiting. */
74877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        if (thread->waitMonitor != NULL) {
74977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro            pthread_cond_signal(&thread->waitCond);
75030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            pthread_mutex_unlock(&thread->waitMutex);
75130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            return;
75277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        }
75377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        pthread_mutex_unlock(&thread->waitMutex);
754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Notify all threads waiting on this monitor.
759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void notifyAllMonitor(Thread* self, Monitor* mon)
761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
76277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    Thread* thread;
76377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
76471938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    assert(self != NULL);
76571938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    assert(mon != NULL);
76671938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro
76794338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    /* Make sure that we hold the lock. */
76871938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    if (mon->owner != self) {
769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "object not locked by thread before notifyAll()");
771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
77377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    /* Signal all threads in the wait set. */
77477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    while (mon->waitSet != NULL) {
77577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        thread = mon->waitSet;
77677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        mon->waitSet = thread->waitNext;
77777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        thread->waitNext = NULL;
77877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        pthread_mutex_lock(&thread->waitMutex);
77977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        /* Check to see if the thread is still waiting. */
78077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        if (thread->waitMonitor != NULL) {
78177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro            pthread_cond_signal(&thread->waitCond);
78277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        }
78377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        pthread_mutex_unlock(&thread->waitMutex);
784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
78866bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro * Changes the shape of a monitor from thin to fat, preserving the
78966bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro * internal lock state.  The calling thread must own the lock.
79066bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro */
79166bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapirostatic void inflateMonitor(Thread *self, Object *obj)
79266bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro{
79366bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    Monitor *mon;
79466bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    u4 thin;
79566bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro
79666bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    assert(self != NULL);
79766bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    assert(obj != NULL);
79866bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    assert(LW_SHAPE(obj->lock) == LW_SHAPE_THIN);
79966bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    assert(LW_LOCK_OWNER(obj->lock) == self->threadId);
80066bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    /* Allocate and acquire a new monitor. */
80166bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    mon = dvmCreateMonitor(obj);
80266bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    lockMonitor(self, mon);
80366bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    /* Propagate the lock state. */
80466bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    thin = obj->lock;
80566bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    mon->lockCount = LW_LOCK_COUNT(thin);
80666bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    thin &= LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT;
80766bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    thin |= (u4)mon | LW_SHAPE_FAT;
80866bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    /* Publish the updated lock word. */
80966bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    MEM_BARRIER();
81066bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    obj->lock = thin;
81166bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro}
81266bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro
81366bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro/*
814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Implements monitorenter for "synchronized" stuff.
815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This does not fail or throw an exception (unless deadlock prediction
817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is enabled and set to "err" mode).
818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmLockObject(Thread* self, Object *obj)
820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
821147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    volatile u4 *thinp;
822147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    ThreadStatus oldStatus;
823147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    useconds_t sleepDelay;
824147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    const useconds_t maxSleepDelay = 1 << 20;
825147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    u4 thin, newThin, threadId;
826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
827147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    assert(self != NULL);
828147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    assert(obj != NULL);
829147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    threadId = self->threadId;
830147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    thinp = &obj->lock;
831147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiroretry:
832147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    thin = *thinp;
833147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
834147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro        /*
835147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro         * The lock is a thin lock.  The owner field is used to
836147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro         * determine the acquire method, ordered by cost.
837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
838147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro        if (LW_LOCK_OWNER(thin) == threadId) {
839147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            /*
840147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * The calling thread owns the lock.  Increment the
841147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * value of the recursion count field.
842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
843147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            obj->lock += 1 << LW_LOCK_COUNT_SHIFT;
844147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro        } else if (LW_LOCK_OWNER(thin) == 0) {
845147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            /*
846147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * The lock is unowned.  Install the thread id of the
847147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * calling thread into the owner field.  This is the
848147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * common case.  In performance critical code the JIT
849147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * will have tried this before calling out to the VM.
850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
851147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            newThin = thin | (threadId << LW_LOCK_OWNER_SHIFT);
852147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            if (!ATOMIC_CMP_SWAP((int32_t *)thinp, thin, newThin)) {
853147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                /*
854147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                 * The acquire failed.  Try again.
855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
856147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                goto retry;
857147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            }
858147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro        } else {
859147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            LOG_THIN("(%d) spin on lock %p: %#x (%#x) %#x",
860147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                     threadId, &obj->lock, 0, *thinp, thin);
861147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            /*
862147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * The lock is owned by another thread.  Notify the VM
863147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * that we are about to wait.
864147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             */
865147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            oldStatus = dvmChangeStatus(self, THREAD_MONITOR);
866147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            /*
867147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * Spin until the thin lock is released or inflated.
868147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             */
869147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            sleepDelay = 0;
870147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            for (;;) {
871147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                thin = *thinp;
872147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                /*
873147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                 * Check the shape of the lock word.  Another thread
874147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                 * may have inflated the lock while we were waiting.
875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
876147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
877147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                    if (LW_LOCK_OWNER(thin) == 0) {
878147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                        /*
879147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                         * The lock has been released.  Install the
880147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                         * thread id of the calling thread into the
881147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                         * owner field.
882147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                         */
883147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                        newThin = thin | (threadId << LW_LOCK_OWNER_SHIFT);
884147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                        if (ATOMIC_CMP_SWAP((int32_t *)thinp,
885147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                                            thin, newThin)) {
886147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                            /*
887147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                             * The acquire succeed.  Break out of the
888147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                             * loop and proceed to inflate the lock.
889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                             */
890147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                            break;
891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        }
892147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                    } else {
893147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                        /*
894147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                         * The lock has not been released.  Yield so
895147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                         * the owning thread can run.
896147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                         */
897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        if (sleepDelay == 0) {
898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            sched_yield();
899147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                            sleepDelay = 1000;
900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        } else {
901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            usleep(sleepDelay);
902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            if (sleepDelay < maxSleepDelay / 2) {
903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                sleepDelay *= 2;
904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            }
905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        }
906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
907147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                } else {
908147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                    /*
909147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                     * The thin lock was inflated by another thread.
910147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                     * Let the VM know we are no longer waiting and
911147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                     * try again.
912147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                     */
913147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                    LOG_THIN("(%d) lock %p surprise-fattened",
914147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                             threadId, &obj->lock);
915147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                    dvmChangeStatus(self, oldStatus);
916147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                    goto retry;
917147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                }
918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
919147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            LOG_THIN("(%d) spin on lock done %p: %#x (%#x) %#x",
920147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                     threadId, &obj->lock, 0, *thinp, thin);
921147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            /*
922147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * We have acquired the thin lock.  Let the VM know that
923147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * we are no longer waiting.
924147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             */
925147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            dvmChangeStatus(self, oldStatus);
926147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            /*
927147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * Fatten the lock.
928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
92966bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro            inflateMonitor(self, obj);
930147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            LOG_THIN("(%d) lock %p fattened", threadId, &obj->lock);
931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
932147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    } else {
933147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro        /*
934147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro         * The lock is a fat lock.
935147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro         */
936147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro        assert(LW_MONITOR(obj->lock) != NULL);
937147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro        lockMonitor(self, LW_MONITOR(obj->lock));
938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * See if we were allowed to grab the lock at this time.  We do it
942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * *after* acquiring the lock, rather than before, so that we can
943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * freely update the Monitor struct.  This seems counter-intuitive,
944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * but our goal is deadlock *prediction* not deadlock *prevention*.
945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (If we actually deadlock, the situation is easy to diagnose from
946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * a thread dump, so there's no point making a special effort to do
947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the checks before the lock is held.)
948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * This needs to happen before we add the object to the thread's
950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * monitor list, so we can tell the difference between first-lock and
951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * re-lock.
952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * It's also important that we do this while in THREAD_RUNNING, so
954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that we don't interfere with cleanup operations in the GC.
955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.deadlockPredictMode != kDPOff) {
957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (self->status != THREAD_RUNNING) {
958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Bad thread status (%d) in DP\n", self->status);
959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmDumpThread(self, false);
960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!dvmCheckException(self));
963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        updateDeadlockPrediction(self, obj);
964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmCheckException(self)) {
965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * If we're throwing an exception here, we need to free the
967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * lock.  We add the object to the thread's monitor list so the
968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * "unlock" code can remove it.
969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAddToMonitorList(self, obj, false);
971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmUnlockObject(self, obj);
972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGV("--- unlocked, pending is '%s'\n",
973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmGetException(self)->clazz->descriptor);
974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Add the locked object, and the current stack trace, to the list
979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * held by the Thread object.  If deadlock prediction isn't on,
980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * don't capture the stack trace.
981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmAddToMonitorList(self, obj, gDvm.deadlockPredictMode != kDPOff);
983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#elif defined(WITH_MONITOR_TRACKING)
984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Add the locked object to the list held by the Thread object.
986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmAddToMonitorList(self, obj, false);
988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Implements monitorexit for "synchronized" stuff.
993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * On failure, throws an exception and returns "false".
995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmUnlockObject(Thread* self, Object *obj)
997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
99894338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    u4 thin;
999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1000ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro    assert(self != NULL);
1001ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro    assert(self->status == THREAD_RUNNING);
1002ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro    assert(obj != NULL);
1003ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro    /*
1004ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro     * Cache the lock word as its value can change while we are
1005ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro     * examining its state.
1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1007147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    thin = obj->lock;
1008ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro    if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
1009ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro        /*
1010ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro         * The lock is thin.  We must ensure that the lock is owned
1011ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro         * by the given thread before unlocking it.
1012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1013ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro        if (LW_LOCK_OWNER(thin) == self->threadId) {
1014ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro            /*
1015ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro             * We are the lock owner.  It is safe to update the lock
1016ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro             * without CAS as lock ownership guards the lock itself.
1017ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro             */
1018ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro            if (LW_LOCK_COUNT(thin) == 0) {
1019ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                /*
1020ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                 * The lock was not recursively acquired, the common
1021ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                 * case.  Unlock by clearing all bits except for the
1022ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                 * hash state.
1023ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                 */
1024147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                obj->lock &= (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT);
1025ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro            } else {
1026ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                /*
1027ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                 * The object was recursively acquired.  Decrement the
1028ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                 * lock recursion count field.
1029ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                 */
1030147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                obj->lock -= 1 << LW_LOCK_COUNT_SHIFT;
1031ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro            }
1032ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro        } else {
1033ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro            /*
1034ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro             * We do not own the lock.  The JVM spec requires that we
1035ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro             * throw an exception in this case.
1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
1038ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                              "unlock of unowned monitor");
1039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
1040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1042ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro        /*
1043ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro         * The lock is fat.  We must check to see if unlockMonitor has
1044ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro         * raised any exceptions before continuing.
1045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
10468d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        assert(LW_MONITOR(obj->lock) != NULL);
10478d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        if (!unlockMonitor(self, LW_MONITOR(obj->lock))) {
1048ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro            /*
1049ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro             * An exception has been raised.  Do not fall through.
1050ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro             */
1051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
1052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_MONITOR_TRACKING
1056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Remove the object from the Thread's list.
1058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmRemoveFromMonitorList(self, obj);
1060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
1063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Object.wait().  Also called for class init.
1067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmObjectWait(Thread* self, Object *obj, s8 msec, s4 nsec,
1069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool interruptShouldThrow)
1070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
107166bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    Monitor* mon;
10728d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    u4 thin = obj->lock;
1073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* If the lock is still thin, we need to fatten it.
1075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
107694338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
1077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Make sure that 'self' holds the lock.
1078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
107994338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        if (LW_LOCK_OWNER(thin) != self->threadId) {
1080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
1081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "object not locked by thread before wait()");
1082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
1083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* This thread holds the lock.  We need to fatten the lock
1086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * so 'self' can block on it.  Don't update the object lock
1087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * field yet, because 'self' needs to acquire the lock before
1088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * any other thread gets a chance.
1089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
109066bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro        inflateMonitor(self, obj);
109166bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro        LOG_THIN("(%d) lock %p fattened by wait() to count %d",
109266bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro                 self->threadId, &obj->lock, mon->lockCount);
1093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
109466bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    mon = LW_MONITOR(obj->lock);
1095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    waitMonitor(self, mon, msec, nsec, interruptShouldThrow);
1096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Object.notify().
1100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmObjectNotify(Thread* self, Object *obj)
1102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
11038d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    u4 thin = obj->lock;
1104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* If the lock is still thin, there aren't any waiters;
1106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * waiting on an object forces lock fattening.
1107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
110894338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
1109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Make sure that 'self' holds the lock.
1110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
111194338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        if (LW_LOCK_OWNER(thin) != self->threadId) {
1112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
1113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "object not locked by thread before notify()");
1114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
1115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* no-op;  there are no waiters to notify.
1118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* It's a fat lock.
1121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
112294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        notifyMonitor(self, LW_MONITOR(thin));
1123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Object.notifyAll().
1128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmObjectNotifyAll(Thread* self, Object *obj)
1130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
11318d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    u4 thin = obj->lock;
1132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* If the lock is still thin, there aren't any waiters;
1134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * waiting on an object forces lock fattening.
1135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
113694338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
1137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Make sure that 'self' holds the lock.
1138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
113994338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        if (LW_LOCK_OWNER(thin) != self->threadId) {
1140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
1141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "object not locked by thread before notifyAll()");
1142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
1143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* no-op;  there are no waiters to notify.
1146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* It's a fat lock.
1149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
115094338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        notifyAllMonitor(self, LW_MONITOR(thin));
1151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This implements java.lang.Thread.sleep(long msec, int nsec).
1156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The sleep is interruptible by other threads, which means we can't just
1158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * plop into an OS sleep call.  (We probably could if we wanted to send
1159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * signals around and rely on EINTR, but that's inefficient and relies
1160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * on native code respecting our signal mask.)
1161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We have to do all of this stuff for Object.wait() as well, so it's
1163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * easiest to just sleep on a private Monitor.
1164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It appears that we want sleep(0,0) to go through the motions of sleeping
1166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * for a very short duration, rather than just returning.
1167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmThreadSleep(u8 msec, u4 nsec)
1169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
1171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon = gDvm.threadSleepMon;
1172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* sleep(0,0) wakes up immediately, wait(0,0) means wait forever; adjust */
1174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (msec == 0 && nsec == 0)
1175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        nsec++;
1176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    lockMonitor(self, mon);
1178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    waitMonitor(self, mon, msec, nsec, true);
1179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unlockMonitor(self, mon);
1180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Implement java.lang.Thread.interrupt().
1184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
118577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapirovoid dvmThreadInterrupt(Thread* thread)
1186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
118777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(thread != NULL);
118877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
118977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    pthread_mutex_lock(&thread->waitMutex);
119077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
119177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    /*
119277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     * If the interrupted flag is already set no additional action is
119377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     * required.
119477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     */
119577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (thread->interrupted == true) {
119677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        pthread_mutex_unlock(&thread->waitMutex);
119777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        return;
119877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
119977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
1200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Raise the "interrupted" flag.  This will cause it to bail early out
1202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * of the next wait() attempt, if it's not currently waiting on
1203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * something.
1204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    thread->interrupted = true;
1206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MEM_BARRIER();
1207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Is the thread waiting?
1210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Note that fat vs. thin doesn't matter here;  waitMonitor
1212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * is only set when a thread actually waits on a monitor,
1213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * which implies that the monitor has already been fattened.
1214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
121577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (thread->waitMonitor != NULL) {
121677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        pthread_cond_signal(&thread->waitCond);
1217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
121977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    pthread_mutex_unlock(&thread->waitMutex);
1220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
122230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro#ifndef WITH_COPYING_GC
122394338aadf8355b28846f0d21c49142ca29479dc4Carl Shapirou4 dvmIdentityHashCode(Object *obj)
122494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro{
122594338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    return (u4)obj;
122694338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro}
122730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro#else
122830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapirostatic size_t arrayElementWidth(const ArrayObject *array)
122930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro{
123030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    const char *descriptor;
123130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro
123230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    if (dvmIsObjectArray(array)) {
123330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro	return sizeof(Object *);
123430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    } else {
123530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro	descriptor = array->obj.clazz->descriptor;
123630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        switch (descriptor[1]) {
123730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        case 'B': return 1;  /* byte */
123830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        case 'C': return 2;  /* char */
123930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        case 'D': return 8;  /* double */
124030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        case 'F': return 4;  /* float */
124130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        case 'I': return 4;  /* int */
124230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        case 'J': return 8;  /* long */
124330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        case 'S': return 2;  /* short */
124430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        case 'Z': return 1;  /* boolean */
124530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        }
124630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    }
124730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    LOGE("object %p has an unhandled descriptor '%s'", array, descriptor);
124830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    dvmDumpThread(dvmThreadSelf(), false);
124930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    dvmAbort();
125030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    return 0;  /* Quiet the compiler. */
125130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro}
125230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro
125330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapirostatic size_t arrayObjectLength(const ArrayObject *array)
125430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro{
125530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    size_t length;
125630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro
125730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    length = offsetof(ArrayObject, contents);
125830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    length += array->length * arrayElementWidth(array);
125930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    return length;
126030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro}
126130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro
126230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro/*
126330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * Returns the identity hash code of the given object.
126430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */
126530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapirou4 dvmIdentityHashCode(Object *obj)
126630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro{
126730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    Thread *self, *thread;
126830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    volatile u4 *lw;
126930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    size_t length;
127030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    u4 lock, owner, hashState;
127130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro
127230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    if (obj == NULL) {
127330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
127430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * Null is defined to have an identity hash code of 0.
127530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
127630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        return 0;
127730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    }
127830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    lw = &obj->lock;
127930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiroretry:
128030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    hashState = LW_HASH_STATE(*lw);
128130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    if (hashState == LW_HASH_STATE_HASHED) {
128230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
128330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * The object has been hashed but has not had its hash code
128430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * relocated by the garbage collector.  Use the raw object
128530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * address.
128630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
128730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        return (u4)obj >> 3;
128830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    } else if (hashState == LW_HASH_STATE_HASHED_AND_MOVED) {
128930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
129030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * The object has been hashed and its hash code has been
129130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * relocated by the collector.  Use the value of the naturally
129230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * aligned word following the instance data.
129330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
129430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISARRAY)) {
129530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            length = arrayObjectLength((ArrayObject *)obj);
129630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            length = (length + 3) & ~3;
129730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        } else {
129830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            length = obj->clazz->objectSize;
129930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        }
130030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        return *(u4 *)(((char *)obj) + length);
130130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    } else if (hashState == LW_HASH_STATE_UNHASHED) {
130230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
130330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * The object has never been hashed.  Change the hash state to
130430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * hashed and use the raw object address.
130530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
130630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        self = dvmThreadSelf();
130730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        if (self->threadId == lockOwner(obj)) {
130830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            /*
130930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * We already own the lock so we can update the hash state
131030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * directly.
131130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             */
131230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            *lw |= (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT);
131330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            return (u4)obj >> 3;
131430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        }
131530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
131630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * We do not own the lock.  Try acquiring the lock.  Should
131730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * this fail, we must suspend the owning thread.
131830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
131930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        if (LW_SHAPE(*lw) == LW_SHAPE_THIN) {
132030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            /*
132130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * If the lock is thin assume it is unowned.  We simulate
132230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * an acquire, update, and release with a single CAS.
132330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             */
132430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            lock = DVM_LOCK_INITIAL_THIN_VALUE;
132530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            lock |= (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT);
132630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            if (ATOMIC_CMP_SWAP((int32_t *)lw,
132730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                                (int32_t)DVM_LOCK_INITIAL_THIN_VALUE,
132830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                                (int32_t)lock)) {
132930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                /*
133030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                 * A new lockword has been installed with a hash state
133130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                 * of hashed.  Use the raw object address.
133230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                 */
133330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                return (u4)obj >> 3;
133430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            }
133530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        } else {
133630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            if (tryLockMonitor(self, LW_MONITOR(*lw))) {
133730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                /*
133830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                 * The monitor lock has been acquired.  Change the
133930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                 * hash state to hashed and use the raw object
134030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                 * address.
134130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                 */
134230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                *lw |= (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT);
134330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                unlockMonitor(self, LW_MONITOR(*lw));
134430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                return (u4)obj >> 3;
134530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            }
134630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        }
134730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
134830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * At this point we have failed to acquire the lock.  We must
134930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * identify the owning thread and suspend it.
135030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
135130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        dvmLockThreadList(self);
135230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
135330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * Cache the lock word as its value can change between
135430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * determining its shape and retrieving its owner.
135530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
135630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        lock = *lw;
135730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        if (LW_SHAPE(lock) == LW_SHAPE_THIN) {
135830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            /*
135930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * Find the thread with the corresponding thread id.
136030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             */
136130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            owner = LW_LOCK_OWNER(lock);
136230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            assert(owner != self->threadId);
136330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            /*
136430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * If the lock has no owner do not bother scanning the
136530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * thread list and fall through to the failure handler.
136630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             */
136730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            thread = owner ? gDvm.threadList : NULL;
136830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            while (thread != NULL) {
136930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                if (thread->threadId == owner) {
137030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                    break;
137130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                }
137230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                thread = thread->next;
137330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            }
137430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        } else {
137530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            thread = LW_MONITOR(lock)->owner;
137630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        }
137730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
137830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * If thread is NULL the object has been released since the
137930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * thread list lock was acquired.  Try again.
138030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
138130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        if (thread == NULL) {
138230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            dvmUnlockThreadList();
138330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            goto retry;
138430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        }
138530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
138630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * Wait for the owning thread to suspend.
138730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
138830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        dvmSuspendThread(thread);
138930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        if (dvmHoldsLock(thread, obj)) {
139030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            /*
139130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * The owning thread has been suspended.  We can safely
139230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * change the hash state to hashed.
139330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             */
139430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            *lw |= (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT);
139530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            dvmResumeThread(thread);
139630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            dvmUnlockThreadList();
139730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            return (u4)obj >> 3;
139830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        }
139930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
140030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * The wrong thread has been suspended.  Try again.
140130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
140230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        dvmResumeThread(thread);
140330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        dvmUnlockThreadList();
140430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        goto retry;
140530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    }
140630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    LOGE("object %p has an unknown hash state %#x", obj, hashState);
140730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    dvmDumpThread(dvmThreadSelf(), false);
140830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    dvmAbort();
140930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    return 0;  /* Quiet the compiler. */
141030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro}
141130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro#endif  /* WITH_COPYING_GC */
1412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
1414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
1416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Deadlock prediction
1417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
1418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe idea is to predict the possibility of deadlock by recording the order
1421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectin which monitors are acquired.  If we see an attempt to acquire a lock
1422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectout of order, we can identify the locks and offending code.
1423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectTo make this work, we need to keep track of the locks held by each thread,
1425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectand create history trees for each lock.  When a thread tries to acquire
1426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecta new lock, we walk through the "history children" of the lock, looking
1427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfor a match with locks the thread already holds.  If we find a match,
1428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectit means the thread has made a request that could result in a deadlock.
1429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectTo support recursive locks, we always allow re-locking a currently-held
1431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectlock, and maintain a recursion depth count.
1432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectAn ASCII-art example, where letters represent Objects:
1434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        A
1436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project       /|\
1437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project      / | \
1438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     B  |  D
1439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project      \ |
1440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project       \|
1441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        C
1442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe above is the tree we'd have after handling Object synchronization
1444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsequences "ABC", "AC", "AD".  A has three children, {B, C, D}.  C is also
1445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecta child of B.  (The lines represent pointers between parent and child.
1446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectEvery node can have multiple parents and multiple children.)
1447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectIf we hold AC, and want to lock B, we recursively search through B's
1449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchildren to see if A or C appears.  It does, so we reject the attempt.
1450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project(A straightforward way to implement it: add a link from C to B, then
1451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectdetermine whether the graph starting at B contains a cycle.)
1452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectIf we hold AC and want to lock D, we would succeed, creating a new link
1454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfrom C to D.
1455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe lock history and a stack trace is attached to the Object's Monitor
1457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstruct, which means we need to fatten every Object we lock (thin locking
1458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectis effectively disabled).  If we don't need the stack trace we can
1459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectavoid fattening the leaf nodes, only fattening objects that need to hold
1460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecthistory trees.
1461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectUpdates to Monitor structs are only allowed for the thread that holds
1463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe Monitor, so we actually do most of our deadlock prediction work after
1464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe lock has been acquired.
1465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectWhen an object with a monitor is GCed, we need to remove it from the
1467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecthistory trees.  There are two basic approaches:
1468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (1) For through the entire set of known monitors, search all child
1469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     lists for the object in question.  This is rather slow, resulting
1470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     in GC passes that take upwards of 10 seconds to complete.
1471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (2) Maintain "parent" pointers in each node.  Remove the entries as
1472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     required.  This requires additional storage and maintenance for
1473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     every operation, but is significantly faster at GC time.
1474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectFor each GCed object, we merge all of the object's children into each of
1475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe object's parents.
1476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project*/
1477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if !defined(WITH_MONITOR_TRACKING)
1479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# error "WITH_DEADLOCK_PREDICTION requires WITH_MONITOR_TRACKING"
1480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Clear out the contents of an ExpandingObjectList, freeing any
1484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * dynamic allocations.
1485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void expandObjClear(ExpandingObjectList* pList)
1487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pList->list != NULL) {
1489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(pList->list);
1490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pList->list = NULL;
1491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pList->alloc = pList->count = 0;
1493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the number of objects currently stored in the list.
1497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline int expandBufGetCount(const ExpandingObjectList* pList)
1499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return pList->count;
1501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the Nth entry from the list.
1505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline Object* expandBufGetEntry(const ExpandingObjectList* pList,
1507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i)
1508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return pList->list[i];
1510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add a new entry to the list.
1514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We don't check for or try to enforce uniqueness.  It's expected that
1516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the higher-level code does this for us.
1517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void expandObjAddEntry(ExpandingObjectList* pList, Object* obj)
1519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pList->count == pList->alloc) {
1521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* time to expand */
1522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object** newList;
1523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pList->alloc == 0)
1525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pList->alloc = 4;
1526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
1527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pList->alloc *= 2;
1528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("expanding %p to %d\n", pList, pList->alloc);
1529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newList = realloc(pList->list, pList->alloc * sizeof(Object*));
1530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (newList == NULL) {
1531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Failed expanding DP object list (alloc=%d)\n", pList->alloc);
1532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
1533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pList->list = newList;
1535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pList->list[pList->count++] = obj;
1538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if the element was successfully removed.
1542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool expandObjRemoveEntry(ExpandingObjectList* pList, Object* obj)
1544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = pList->count-1; i >= 0; i--) {
1548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pList->list[i] == obj)
1549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (i < 0)
1552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
1553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (i != pList->count-1) {
1555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The order of elements is not important, so we just copy the
1557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * last entry into the new slot.
1558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //memmove(&pList->list[i], &pList->list[i+1],
1560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    (pList->count-1 - i) * sizeof(pList->list[0]));
1561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pList->list[i] = pList->list[pList->count-1];
1562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pList->count--;
1565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pList->list[pList->count] = (Object*) 0xdecadead;
1566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
1567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if "obj" appears in the list.
1571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool expandObjHas(const ExpandingObjectList* pList, Object* obj)
1573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < pList->count; i++) {
1577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pList->list[i] == obj)
1578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
1579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return false;
1581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Print the list contents to stdout.  For debugging.
1585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void expandObjDump(const ExpandingObjectList* pList)
1587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < pList->count; i++)
1590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(" %p", pList->list[i]);
1591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Check for duplicate entries.  Returns the index of the first instance
1595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of the duplicated value, or -1 if no duplicates were found.
1596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int expandObjCheckForDuplicates(const ExpandingObjectList* pList)
1598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i, j;
1600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < pList->count-1; i++) {
1601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (j = i + 1; j < pList->count; j++) {
1602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (pList->list[i] == pList->list[j]) {
1603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return i;
1604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return -1;
1609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Determine whether "child" appears in the list of objects associated
1614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * with the Monitor in "parent".  If "parent" is a thin lock, we return
1615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * false immediately.
1616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool objectInChildList(const Object* parent, Object* child)
1618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
16198d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    u4 lock = parent->lock;
1620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!IS_LOCK_FAT(&lock)) {
1621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //LOGI("on thin\n");
1622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
1623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
16258d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    return expandObjHas(&LW_MONITOR(lock)->historyChildren, child);
1626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Print the child list.
1630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void dumpKids(Object* parent)
1632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
16338d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    Monitor* mon = LW_MONITOR(parent->lock);
1634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("Children of %p:", parent);
1636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    expandObjDump(&mon->historyChildren);
1637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("\n");
1638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add "child" to the list of children in "parent", and add "parent" to
1642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the list of parents in "child".
1643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void linkParentToChild(Object* parent, Object* child)
1645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
16468d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    //assert(LW_MONITOR(parent->lock)->owner == dvmThreadSelf());   // !owned for merge
1647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&parent->lock));
1648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&child->lock));
1649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(parent != child);
1650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon;
1651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
16528d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    mon = LW_MONITOR(parent->lock);
1653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!expandObjHas(&mon->historyChildren, child));
1654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    expandObjAddEntry(&mon->historyChildren, child);
1655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
16568d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    mon = LW_MONITOR(child->lock);
1657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!expandObjHas(&mon->historyParents, parent));
1658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    expandObjAddEntry(&mon->historyParents, parent);
1659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Remove "child" from the list of children in "parent".
1664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void unlinkParentFromChild(Object* parent, Object* child)
1666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
16678d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    //assert(LW_MONITOR(parent->lock)->owner == dvmThreadSelf());   // !owned for GC
1668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&parent->lock));
1669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&child->lock));
1670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(parent != child);
1671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon;
1672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
16738d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    mon = LW_MONITOR(parent->lock);
1674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!expandObjRemoveEntry(&mon->historyChildren, child)) {
1675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("WARNING: child %p not found in parent %p\n", child, parent);
1676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!expandObjHas(&mon->historyChildren, child));
1678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(expandObjCheckForDuplicates(&mon->historyChildren) < 0);
1679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
16808d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    mon = LW_MONITOR(child->lock);
1681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!expandObjRemoveEntry(&mon->historyParents, parent)) {
1682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("WARNING: parent %p not found in child %p\n", parent, child);
1683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!expandObjHas(&mon->historyParents, parent));
1685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(expandObjCheckForDuplicates(&mon->historyParents) < 0);
1686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Log the monitors held by the current thread.  This is done as part of
1691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * flagging an error.
1692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void logHeldMonitors(Thread* self)
1694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* name = NULL;
1696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    name = dvmGetThreadName(self);
1698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGW("Monitors currently held by thread (threadid=%d '%s')\n",
1699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        self->threadId, name);
1700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGW("(most-recently-acquired on top):\n");
1701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(name);
1702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LockedObjectData* lod = self->pLockedObjects;
1704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (lod != NULL) {
1705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("--- object %p[%d] (%s)\n",
1706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lod->obj, lod->recursionCount, lod->obj->clazz->descriptor);
1707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLogRawStackTrace(lod->rawStackTrace, lod->stackDepth);
1708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        lod = lod->next;
1710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Recursively traverse the object hierarchy starting at "obj".  We mark
1715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ourselves on entry and clear the mark on exit.  If we ever encounter
1716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a marked object, we have a cycle.
1717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if all is well, "false" if we found a cycle.
1719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool traverseTree(Thread* self, const Object* obj)
1721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&obj->lock));
17238d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    Monitor* mon = LW_MONITOR(obj->lock);
1724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Have we been here before?
1727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon->historyMark) {
1729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int* rawStackTrace;
1730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int stackDepth;
1731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("%s\n", kStartBanner);
1733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("Illegal lock attempt:\n");
1734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("--- object %p (%s)\n", obj, obj->clazz->descriptor);
1735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        rawStackTrace = dvmFillInStackTraceRaw(self, &stackDepth);
1737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLogRawStackTrace(rawStackTrace, stackDepth);
1738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(rawStackTrace);
1739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW(" ");
1741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        logHeldMonitors(self);
1742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW(" ");
1744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("Earlier, the following lock order (from last to first) was\n");
1745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("established -- stack trace is from first successful lock):\n");
1746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
1747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->historyMark = true;
1749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Examine the children.  We do NOT hold these locks, so they might
1752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * very well transition from thin to fat or change ownership while
1753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we work.
1754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * NOTE: we rely on the fact that they cannot revert from fat to thin
1756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * while we work.  This is currently a safe assumption.
1757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We can safely ignore thin-locked children, because by definition
1759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * they have no history and are leaf nodes.  In the current
1760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * implementation we always fatten the locks to provide a place to
1761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * hang the stack trace.
1762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExpandingObjectList* pList = &mon->historyChildren;
1764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
1766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const Object* child = expandBufGetEntry(pList, i);
17678d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        u4 lock = child->lock;
1768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!IS_LOCK_FAT(&lock))
1769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            continue;
1770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!traverseTree(self, child)) {
1771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("--- object %p (%s)\n", obj, obj->clazz->descriptor);
1772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLogRawStackTrace(mon->historyRawStackTrace,
1773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                mon->historyStackDepth);
1774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mon->historyMark = false;
1775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
1776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->historyMark = false;
1780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
1782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Update the deadlock prediction tree, based on the current thread
1786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * acquiring "acqObj".  This must be called before the object is added to
1787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the thread's list of held monitors.
1788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the thread already holds the lock (recursion), or this is a known
1790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * lock configuration, we return without doing anything.  Otherwise, we add
1791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a link from the most-recently-acquired lock in this thread to "acqObj"
1792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * after ensuring that the parent lock is "fat".
1793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This MUST NOT be called while a GC is in progress in another thread,
1795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because we assume exclusive access to history trees in owned monitors.
1796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void updateDeadlockPrediction(Thread* self, Object* acqObj)
1798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LockedObjectData* lod;
1800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LockedObjectData* mrl;
1801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Quick check for recursive access.
1804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    lod = dvmFindInMonitorList(self, acqObj);
1806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (lod != NULL) {
1807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("+++ DP: recursive %p\n", acqObj);
1808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Make the newly-acquired object's monitor "fat".  In some ways this
1813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * isn't strictly necessary, but we need the GC to tell us when
1814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * "interesting" objects go away, and right now the only way to make
1815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * an object look interesting is to give it a monitor.
1816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * This also gives us a place to hang a stack trace.
1818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Our thread holds the lock, so we're allowed to rewrite the lock
1820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * without worrying that something will change out from under us.
1821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!IS_LOCK_FAT(&acqObj->lock)) {
1823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("fattening lockee %p (recur=%d)\n",
182494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro            acqObj, LW_LOCK_COUNT(acqObj->lock.thin));
182566bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro        inflateMonitor(self, acqObj);
1826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* if we don't have a stack trace for this monitor, establish one */
18298d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    if (LW_MONITOR(acqObj->lock)->historyRawStackTrace == NULL) {
18308d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        Monitor* mon = LW_MONITOR(acqObj->lock);
1831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon->historyRawStackTrace = dvmFillInStackTraceRaw(self,
1832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            &mon->historyStackDepth);
1833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We need to examine and perhaps modify the most-recently-locked
1837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * monitor.  We own that, so there's no risk of another thread
1838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * stepping on us.
1839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Retrieve the most-recently-locked entry from our thread.
1841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mrl = self->pLockedObjects;
1843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mrl == NULL)
1844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;         /* no other locks held */
1845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Do a quick check to see if "acqObj" is a direct descendant.  We can do
1848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * this without holding the global lock because of our assertion that
1849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * a GC is not running in parallel -- nobody except the GC can
1850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * modify a history list in a Monitor they don't own, and we own "mrl".
1851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (There might be concurrent *reads*, but no concurrent *writes.)
1852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If we find it, this is a known good configuration, and we're done.
1854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (objectInChildList(mrl->obj, acqObj))
1856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * "mrl" is going to need to have a history tree.  If it's currently
1860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * a thin lock, we make it fat now.  The thin lock might have a
1861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * nonzero recursive lock count, which we need to carry over.
1862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Our thread holds the lock, so we're allowed to rewrite the lock
1864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * without worrying that something will change out from under us.
1865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!IS_LOCK_FAT(&mrl->obj->lock)) {
1867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("fattening parent %p f/b/o child %p (recur=%d)\n",
18688d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro            mrl->obj, acqObj, LW_LOCK_COUNT(mrl->obj->lock));
186966bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro        inflateMonitor(self, mrl->obj);
1870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We haven't seen this configuration before.  We need to scan down
1874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * acqObj's tree to see if any of the monitors in self->pLockedObjects
1875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * appear.  We grab a global lock before traversing or updating the
1876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * history list.
1877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If we find a match for any of our held locks, we know that the lock
1879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * has previously been acquired *after* acqObj, and we throw an error.
1880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The easiest way to do this is to create a link from "mrl" to "acqObj"
1882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * and do a recursive traversal, marking nodes as we cross them.  If
1883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we cross one a second time, we have a cycle and can throw an error.
1884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (We do the flag-clearing traversal before adding the new link, so
1885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that we're guaranteed to terminate.)
1886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If "acqObj" is a thin lock, it has no history, and we can create a
1888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * link to it without additional checks.  [ We now guarantee that it's
1889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * always fat. ]
1890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool failed = false;
1892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLockMutex(&gDvm.deadlockHistoryLock);
1893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    linkParentToChild(mrl->obj, acqObj);
1894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!traverseTree(self, acqObj)) {
1895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("%s\n", kEndBanner);
1896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        failed = true;
1897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* remove the entry so we're still okay when in "warning" mode */
1899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unlinkParentFromChild(mrl->obj, acqObj);
1900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmUnlockMutex(&gDvm.deadlockHistoryLock);
1902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (failed) {
1904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (gDvm.deadlockPredictMode) {
1905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kDPErr:
1906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ldalvik/system/PotentialDeadlockError;", NULL);
1907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kDPAbort:
1909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Aborting due to potential deadlock\n");
1910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
1911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        default:
1913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* warn only */
1914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're removing "child" from existence.  We want to pull all of
1921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * child's children into "parent", filtering out duplicates.  This is
1922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * called during the GC.
1923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This does not modify "child", which might have multiple parents.
1925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void mergeChildren(Object* parent, const Object* child)
1927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon;
1929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&child->lock));
19328d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    mon = LW_MONITOR(child->lock);
1933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExpandingObjectList* pList = &mon->historyChildren;
1934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
1936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* grandChild = expandBufGetEntry(pList, i);
1937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!objectInChildList(parent, grandChild)) {
1939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGVV("+++  migrating %p link to %p\n", grandChild, parent);
1940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            linkParentToChild(parent, grandChild);
1941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGVV("+++  parent %p already links to %p\n", parent, grandChild);
1943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * An object with a fat lock is being collected during a GC pass.  We
1949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * want to remove it from any lock history trees that it is a part of.
1950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This may require updating the history trees in several monitors.  The
1952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * monitor semantics guarantee that no other thread will be accessing
1953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the history trees at the same time.
1954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void removeCollectedObject(Object* obj)
1956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon;
1958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("+++ collecting %p\n", obj);
1960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
1962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We're currently running through the entire set of known monitors.
1964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * This can be somewhat slow.  We may want to keep lists of parents
1965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in each child to speed up GC.
1966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon = gDvm.monitorList;
1968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (mon != NULL) {
1969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* parent = mon->obj;
1970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (parent != NULL) {       /* value nulled for deleted entries */
1971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (objectInChildList(parent, obj)) {
1972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGVV("removing child %p from parent %p\n", obj, parent);
1973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                unlinkParentFromChild(parent, obj);
1974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                mergeChildren(parent, obj);
1975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon = mon->next;
1978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * For every parent of this object:
1983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  - merge all of our children into the parent's child list (creates
1984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *    a two-way link between parent and child)
1985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  - remove ourselves from the parent's child list
1986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExpandingObjectList* pList;
1988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&obj->lock));
19918d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    mon = LW_MONITOR(obj->lock);
1992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pList = &mon->historyParents;
1993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
1994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* parent = expandBufGetEntry(pList, i);
19958d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        Monitor* parentMon = LW_MONITOR(parent->lock);
1996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!expandObjRemoveEntry(&parentMon->historyChildren, obj)) {
1998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("WARNING: child %p not found in parent %p\n", obj, parent);
1999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!expandObjHas(&parentMon->historyChildren, obj));
2001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mergeChildren(parent, obj);
2003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * For every child of this object:
2007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  - remove ourselves from the child's parent list
2008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pList = &mon->historyChildren;
2010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
2011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* child = expandBufGetEntry(pList, i);
20128d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        Monitor* childMon = LW_MONITOR(child->lock);
2013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!expandObjRemoveEntry(&childMon->historyParents, obj)) {
2015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("WARNING: parent %p not found in child %p\n", obj, child);
2016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!expandObjHas(&childMon->historyParents, obj));
2018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif /*WITH_DEADLOCK_PREDICTION*/
2022