Sync.cpp revision 8d7f9b2cd9fe252399ae96a36781bba1242fb93c
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 * NOTE: if we broadcast a notify, and somebody sneaks in a Thread.interrupt
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * before the notify finishes (i.e. before all threads sleeping on the
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * condition variable have awoken), we could end up with a nonzero value for
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "notifying" after everybody is gone because one of the notified threads
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * will actually exit via the "interrupted" path.  This can be detected as
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (notifying + interrupting > waiting), i.e. the number of threads that need
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to be woken is greater than the number waiting.  The fix is to test and
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * adjust "notifying" at the start of the wait() call.
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * -> This is probably not a problem if we notify less than the full set
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * before the interrupt comes in.  If we have four waiters, two pending
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * notifies, and an interrupt hits, we will interrupt one thread and notify
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * two others.  Doesn't matter if the interrupted thread would have been
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * one of the notified.  Count is only screwed up if we have two waiters,
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in which case it's safe to fix it at the start of the next wait().
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h"
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h>
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <unistd.h>
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <pthread.h>
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <time.h>
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <sys/time.h>
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <errno.h>
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define LOG_THIN    LOGV
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION     /* fwd */
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic const char* kStartBanner =
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#";
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic const char* kEndBanner =
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#->";
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unsorted, expanding list of objects.
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is very similar to PointerSet (which came into existence after this),
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * but these are unsorted, uniqueness is not enforced by the "add" function,
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and the base object isn't allocated on the heap.
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct ExpandingObjectList {
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u2          alloc;
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u2          count;
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object**    list;
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} ExpandingObjectList;
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* fwd */
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void updateDeadlockPrediction(Thread* self, Object* obj);
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void removeCollectedObject(Object* obj);
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void expandObjClear(ExpandingObjectList* pList);
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Every Object has a monitor associated with it, but not every Object is
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * actually locked.  Even the ones that are locked do not need a
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * full-fledged monitor until a) there is actual contention or b) wait()
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is called on the Object.
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For Dalvik, we have implemented a scheme similar to the one described
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in Bacon et al.'s "Thin locks: featherweight synchronization for Java"
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (ACM 1998).  Things are even easier for us, though, because we have
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a full 32 bits to work with.
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
9694338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * The two states of an Object's lock are referred to as "thin" and
9794338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * "fat".  A lock may transition from the "thin" state to the "fat"
9894338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * state and this transition is referred to as inflation.  Once a lock
9994338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * has been inflated it remains in the "fat" state indefinitely.
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The lock value itself is stored in Object.lock, which is a union of
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the form:
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     typedef union Lock {
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *         u4          thin;
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *         Monitor*    mon;
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     } Lock;
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10994338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * The LSB of the lock value encodes its state.  If cleared, the lock
11094338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * is in the "thin" state and its bits are formatted as follows:
11171938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro *
11294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro *    [31 ---- 19] [18 ---- 3] [2 ---- 1] [0]
11394338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro *     lock count   thread id  hash state  0
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
11594338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * If set, the lock is in the "fat" state and its bits are formatted
11694338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * as follows:
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
11894338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro *    [31 ---- 3] [2 ---- 1] [0]
11994338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro *      pointer   hash state  1
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For an in-depth description of the mechanics of thin-vs-fat locking,
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * read the paper referred to above.
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Monitors provide:
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  - mutually exclusive access to resources
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  - a way for multiple threads to wait for notification
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In effect, they fill the role of both mutexes and condition variables.
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Only one thread can own the monitor at any time.  There may be several
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * threads waiting on it (the wait call unlocks it).  One or more waiting
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * threads may be getting interrupted or notified at any given time.
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstruct Monitor {
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread*     owner;          /* which thread currently owns the lock? */
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int         lockCount;      /* owner's recursive lock depth */
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object*     obj;            /* what object are we part of [debug only] */
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int         waiting;        /* total #of threads waiting on this */
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int         notifying;      /* #of threads being notified */
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int         interrupting;   /* #of threads being interrupted */
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pthread_mutex_t lock;
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pthread_cond_t  cond;
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor*    next;
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Objects that have been locked immediately after this one in the
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * past.  We use an expanding flat array, allocated on first use, to
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * minimize allocations.  Deletions from the list, expected to be
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * infrequent, are crunched down.
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExpandingObjectList historyChildren;
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We also track parents.  This isn't strictly necessary, but it makes
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the cleanup at GC time significantly faster.
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExpandingObjectList historyParents;
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* used during cycle detection */
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool        historyMark;
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* stack trace, established the first time we locked the object */
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int         historyStackDepth;
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int*        historyRawStackTrace;
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project};
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create and initialize a monitor.
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectMonitor* dvmCreateMonitor(Object* obj)
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon;
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon = (Monitor*) calloc(1, sizeof(Monitor));
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon == NULL) {
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("Unable to allocate monitor\n");
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAbort();
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
18794338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    if (((u4)mon & 7) != 0) {
18894338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        LOGE("Misaligned monitor: %p\n", mon);
18994338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        dvmAbort();
19094338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    }
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->obj = obj;
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmInitMutex(&mon->lock);
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pthread_cond_init(&mon->cond, NULL);
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* replace the head of the list with the new monitor */
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    do {
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon->next = gDvm.monitorList;
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } while (!ATOMIC_CMP_SWAP((int32_t*)(void*)&gDvm.monitorList,
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                              (int32_t)mon->next, (int32_t)mon));
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return mon;
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Release a Monitor.
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void releaseMonitor(Monitor* mon)
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // TODO
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free the monitor list.  Only used when shutting the VM down.
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmFreeMonitorList(void)
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon;
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* nextMon;
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon = gDvm.monitorList;
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (mon != NULL) {
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        nextMon = mon->next;
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        expandObjClear(&mon->historyChildren);
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        expandObjClear(&mon->historyParents);
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(mon->historyRawStackTrace);
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(mon);
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon = nextMon;
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Log some info about our monitors.
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpMonitorInfo(const char* msg)
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if QUIET_ZYGOTE_MONITOR
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.zygote) {
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int totalCount;
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int liveCount;
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    totalCount = liveCount = 0;
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon = gDvm.monitorList;
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (mon != NULL) {
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        totalCount++;
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (mon->obj != NULL)
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            liveCount++;
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon = mon->next;
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGD("%s: monitor list has %d entries (%d live)\n",
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        msg, totalCount, liveCount);
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the object that a monitor is part of.
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectObject* dvmGetMonitorObject(Monitor* mon)
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon == NULL)
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return mon->obj;
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Checks whether the given thread holds the given
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * objects's lock.
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmHoldsLock(Thread* thread, Object* obj)
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
27894338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    u4 thin;
27994338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (thread == NULL || obj == NULL) {
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Since we're reading the lock value multiple times,
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * latch it so that it doesn't change out from under
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * us if we get preempted.
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2888d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    thin = obj->lock;
28994338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    if (LW_SHAPE(thin) == LW_SHAPE_FAT) {
29094338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        return thread == LW_MONITOR(thin)->owner;
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
29294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        return thread->threadId == LW_LOCK_OWNER(thin);
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free the monitor associated with an object and make the object's lock
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * thin again.  This is called during garbage collection.
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3008d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapirovoid dvmFreeObjectMonitor_internal(u4 *lock)
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor *mon;
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* The macro that wraps this function checks IS_LOCK_FAT() first.
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(lock));
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.deadlockPredictMode != kDPOff)
3108d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        removeCollectedObject(LW_MONITOR(*lock)->obj);
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3138d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    mon = LW_MONITOR(*lock);
3148d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    *lock = DVM_LOCK_INITIAL_THIN_VALUE;
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* This lock is associated with an object
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that's being swept.  The only possible way
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * anyone could be holding this lock would be
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * if some JNI code locked but didn't unlock
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the object, in which case we've got some bad
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * native code somewhere.
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(pthread_mutex_trylock(&mon->lock) == 0);
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pthread_mutex_destroy(&mon->lock);
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pthread_cond_destroy(&mon->cond);
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 1
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: unlink from the monitor list (would require a lock)
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// (might not -- the GC suspension may be enough)
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Monitor *next;
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        next = mon->next;
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        expandObjClear(&mon->historyChildren);
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        expandObjClear(&mon->historyParents);
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(mon->historyRawStackTrace);
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        memset(mon, 0, sizeof (*mon));
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon->next = next;
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//free(mon);
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Lock a monitor.
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void lockMonitor(Thread* self, Monitor* mon)
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int cc;
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon->owner == self) {
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon->lockCount++;
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ThreadStatus oldStatus;
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pthread_mutex_trylock(&mon->lock) != 0) {
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* mutex is locked, switch to wait status and sleep on it */
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            oldStatus = dvmChangeStatus(self, THREAD_MONITOR);
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cc = pthread_mutex_lock(&mon->lock);
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(cc == 0);
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmChangeStatus(self, oldStatus);
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon->owner = self;
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(mon->lockCount == 0);
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * "waiting", "notifying", and "interrupting" could all be nonzero
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * if we're locking an object on which other threads are waiting.
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Nothing worth assert()ing about here.
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Try to lock a monitor.
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" on success.
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool tryLockMonitor(Thread* self, Monitor* mon)
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int cc;
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon->owner == self) {
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon->lockCount++;
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cc = pthread_mutex_trylock(&mon->lock);
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (cc == 0) {
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mon->owner = self;
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(mon->lockCount == 0);
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
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
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unlock a monitor.
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns true if the unlock succeeded.
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the unlock failed, an exception will be pending.
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool unlockMonitor(Thread* self, Monitor* mon)
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(mon != NULL);        // can this happen?
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon->owner == self) {
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We own the monitor, so nobody else can be in here.
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (mon->lockCount == 0) {
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int cc;
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mon->owner = NULL;
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cc = pthread_mutex_unlock(&mon->lock);
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(cc == 0);
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mon->lockCount--;
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We don't own this, so we're not allowed to unlock it.
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The JNI spec says that we should throw IllegalMonitorStateException
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * in this case.
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (mon->owner == NULL) {
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //LOGW("Unlock fat %p: not owned\n", mon->obj);
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //LOGW("Unlock fat %p: id %d vs %d\n",
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //    mon->obj, mon->owner->threadId, self->threadId);
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "unlock of unowned monitor");
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Wait on a monitor until timeout, interrupt, or notification.  Used for
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Object.wait() and (somewhat indirectly) Thread.sleep() and Thread.join().
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If another thread calls Thread.interrupt(), we throw InterruptedException
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and return immediately if one of the following are true:
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  - blocked in wait(), wait(long), or wait(long, int) methods of Object
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  - blocked in join(), join(long), or join(long, int) methods of Thread
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  - blocked in sleep(long), or sleep(long, int) methods of Thread
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Otherwise, we set the "interrupted" flag.
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Checks to make sure that "nsec" is in the range 0-999999
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (i.e. fractions of a millisecond) and throws the appropriate
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exception if it isn't.
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The spec allows "spurious wakeups", and recommends that all code using
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Object.wait() do so in a loop.  This appears to derive from concerns
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * about pthread_cond_wait() on multiprocessor systems.  Some commentary
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * on the web casts doubt on whether these can/should occur.
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Since we're allowed to wake up "early", we clamp extremely long durations
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to return at the end of the 32-bit time epoch.
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void waitMonitor(Thread* self, Monitor* mon, s8 msec, s4 nsec,
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool interruptShouldThrow)
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct timespec ts;
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool wasInterrupted = false;
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool timed;
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int cc;
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
47371938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    assert(self != NULL);
47471938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    assert(mon != NULL);
47571938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro
47694338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    /* Make sure that we hold the lock. */
47771938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    if (mon->owner != self) {
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "object not locked by thread before wait()");
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Enforce the timeout range.
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (msec < 0 || nsec < 0 || nsec > 999999) {
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/lang/IllegalArgumentException;",
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "timeout arguments out of range");
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Compute absolute wakeup time, if necessary.
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (msec == 0 && nsec == 0) {
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        timed = false;
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        s8 endSec;
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef HAVE_TIMEDWAIT_MONOTONIC
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        struct timespec now;
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clock_gettime(CLOCK_MONOTONIC, &now);
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        endSec = now.tv_sec + msec / 1000;
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (endSec >= 0x7fffffff) {
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGV("NOTE: end time exceeds epoch\n");
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            endSec = 0x7ffffffe;
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ts.tv_sec = endSec;
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ts.tv_nsec = (now.tv_nsec + (msec % 1000) * 1000 * 1000) + nsec;
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        struct timeval now;
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gettimeofday(&now, NULL);
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        endSec = now.tv_sec + msec / 1000;
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (endSec >= 0x7fffffff) {
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGV("NOTE: end time exceeds epoch\n");
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            endSec = 0x7ffffffe;
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ts.tv_sec = endSec;
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ts.tv_nsec = (now.tv_usec + (msec % 1000) * 1000) * 1000 + nsec;
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* catch rollover */
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (ts.tv_nsec >= 1000000000L) {
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ts.tv_sec++;
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ts.tv_nsec -= 1000000000L;
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        timed = true;
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Make sure "notifying" wasn't screwed up by earlier activity.  If this
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * is wrong we could end up waking up too many people.  (This is a rare
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * situation, but we need to handle it correctly.)
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon->notifying + mon->interrupting > mon->waiting) {
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGD("threadid=%d: bogus mon %d+%d>%d; adjusting\n",
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->threadId, mon->notifying, mon->interrupting,
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mon->waiting);
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(mon->waiting >= mon->interrupting);
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon->notifying = mon->waiting - mon->interrupting;
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Add ourselves to the set of threads waiting on this monitor, and
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * release our hold.  We need to let it go even if we're a few levels
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * deep in a recursive lock, and we need to restore that later.
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The order of operations here isn't significant, because we still
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * hold the pthread mutex.
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int prevLockCount;
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    prevLockCount = mon->lockCount;
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->lockCount = 0;
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->waiting++;
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->owner = NULL;
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Update thread status.  If the GC wakes up, it'll ignore us, knowing
561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that we won't touch any references in this state, and we'll check
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * our suspend mode before we transition out.
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (timed)
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmChangeStatus(self, THREAD_TIMED_WAIT);
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmChangeStatus(self, THREAD_WAIT);
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Tell the thread which monitor we're waiting on.  This is necessary
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * so that Thread.interrupt() can wake us up.  Thread.interrupt needs
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * to gain ownership of the monitor mutex before it can signal us, so
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we're still not worried about race conditions.
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->waitMonitor = mon;
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Handle the case where the thread was interrupted before we called
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * wait().
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (self->interrupted) {
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        wasInterrupted = true;
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto done;
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("threadid=%d: waiting on %p\n", self->threadId, mon);
587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (true) {
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!timed) {
590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cc = pthread_cond_wait(&mon->cond, &mon->lock);
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(cc == 0);
592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef HAVE_TIMEDWAIT_MONOTONIC
594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cc = pthread_cond_timedwait_monotonic(&mon->cond, &mon->lock, &ts);
595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cc = pthread_cond_timedwait(&mon->cond, &mon->lock, &ts);
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (cc == ETIMEDOUT) {
599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGVV("threadid=%d wakeup: timeout\n", self->threadId);
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We woke up because of an interrupt (which does a broadcast) or
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * a notification (which might be a signal or a broadcast).  Figure
607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * out what we need to do.
608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (self->interruptingWait) {
610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * The other thread successfully gained the monitor lock, and
612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * has confirmed that we were waiting on it.  If this is an
613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * interruptible wait, we bail out immediately.  If not, we
614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * continue on.
615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->interruptingWait = false;
617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mon->interrupting--;
618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(self->interrupted);
619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (interruptShouldThrow) {
620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                wasInterrupted = true;
621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGD("threadid=%d wakeup: interrupted\n", self->threadId);
622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGD("threadid=%d wakeup: not interruptible\n", self->threadId);
625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (mon->notifying) {
628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * One or more threads are being notified.  Remove ourselves
630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * from the set.
631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mon->notifying--;
633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGVV("threadid=%d wakeup: notified\n", self->threadId);
634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Looks like we were woken unnecessarily, probably as a
638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * result of another thread being interrupted.  Go back to
639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * sleep.
640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGVV("threadid=%d wakeup: going back to sleep\n", self->threadId);
642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectdone:
646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //if (wasInterrupted) {
647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //    LOGW("threadid=%d: throwing InterruptedException:\n", self->threadId);
648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //    dvmDumpThread(self, false);
649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //}
650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Put everything back.  Again, we hold the pthread mutex, so the order
653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * here isn't significant.
654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->waitMonitor = NULL;
656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->owner = self;
657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->waiting--;
658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->lockCount = prevLockCount;
659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* set self->status back to THREAD_RUNNING, and self-suspend if needed */
661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmChangeStatus(self, THREAD_RUNNING);
662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (wasInterrupted) {
664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We were interrupted while waiting, or somebody interrupted an
666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * un-interruptable thread earlier and we're bailing out immediately.
667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The doc sayeth: "The interrupted status of the current thread is
669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * cleared when this exception is thrown."
670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        self->interrupted = false;
672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (interruptShouldThrow)
673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/InterruptedException;", NULL);
674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Notify one thread waiting on this monitor.
679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void notifyMonitor(Thread* self, Monitor* mon)
681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
68271938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    assert(self != NULL);
68371938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    assert(mon != NULL);
68471938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro
68594338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    /* Make sure that we hold the lock. */
68671938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    if (mon->owner != self) {
687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "object not locked by thread before notify()");
689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Check to see if anybody is there to notify.  We subtract off
694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * threads that are being interrupted and anything that has
695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * potentially already been notified.
696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon->notifying + mon->interrupting < mon->waiting) {
698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* wake up one thread */
699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int cc;
700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("threadid=%d: signaling on %p\n", self->threadId, mon);
702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon->notifying++;
704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cc = pthread_cond_signal(&mon->cond);
705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(cc == 0);
706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("threadid=%d: nobody to signal on %p\n", self->threadId, mon);
708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Notify all threads waiting on this monitor.
713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We keep a count of how many threads we notified, so that our various
715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * counts remain accurate.
716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void notifyAllMonitor(Thread* self, Monitor* mon)
718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
71971938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    assert(self != NULL);
72071938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    assert(mon != NULL);
72171938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro
72294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    /* Make sure that we hold the lock. */
72371938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    if (mon->owner != self) {
724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "object not locked by thread before notifyAll()");
726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->notifying = mon->waiting - mon->interrupting;
730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon->notifying > 0) {
731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int cc;
732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("threadid=%d: broadcasting to %d threads on %p\n",
734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->threadId, mon->notifying, mon);
735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cc = pthread_cond_broadcast(&mon->cond);
737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(cc == 0);
738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("threadid=%d: nobody to broadcast to on %p\n", self->threadId,mon);
740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Implements monitorenter for "synchronized" stuff.
745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This does not fail or throw an exception (unless deadlock prediction
747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is enabled and set to "err" mode).
748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmLockObject(Thread* self, Object *obj)
750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
7518d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    volatile u4 *thinp = &obj->lock;
7528d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    u4 hashState;
75394338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    u4 thin;
754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 threadId = self->threadId;
75594338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    Monitor *mon;
756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* First, try to grab the lock as if it's thin;
758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * this is the common case and will usually succeed.
759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
76094338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    thin = threadId << LW_LOCK_OWNER_SHIFT;
7618d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    thin |= LW_HASH_STATE(*thinp) << LW_HASH_STATE_SHIFT;
762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!ATOMIC_CMP_SWAP((int32_t *)thinp,
763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         (int32_t)DVM_LOCK_INITIAL_THIN_VALUE,
76494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro                         (int32_t)thin)) {
765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* The lock is either a thin lock held by someone (possibly 'self'),
766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * or a fat lock.
767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
76894338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        if (LW_LOCK_OWNER(*thinp) == threadId) {
769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* 'self' is already holding the thin lock; we can just
770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * bump the count.  Atomic operations are not necessary
771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * because only the thread holding the lock is allowed
772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * to modify the Lock field.
773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
77494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro            *thinp += 1 << LW_LOCK_COUNT_SHIFT;
775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* If this is a thin lock we need to spin on it, if it's fat
777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * we need to acquire the monitor.
778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
77994338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro            if (LW_SHAPE(*thinp) == LW_SHAPE_THIN) {
780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ThreadStatus oldStatus;
781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                static const unsigned long maxSleepDelay = 1 * 1024 * 1024;
782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                unsigned long sleepDelay;
783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_THIN("(%d) spin on lock 0x%08x: 0x%08x (0x%08x) 0x%08x\n",
785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         threadId, (uint)&obj->lock,
78694338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro                         DVM_LOCK_INITIAL_THIN_VALUE, *thinp, thin);
787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* The lock is still thin, but some other thread is
789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * holding it.  Let the VM know that we're about
790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * to wait on another thread.
791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                oldStatus = dvmChangeStatus(self, THREAD_MONITOR);
793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* Spin until the other thread lets go.
795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sleepDelay = 0;
797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                do {
798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /* In addition to looking for an unlock,
799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * we need to watch out for some other thread
800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * fattening the lock behind our back.
801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     */
80294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro                    while (LW_LOCK_OWNER(*thinp) != 0) {
80394338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro                        if (LW_SHAPE(*thinp) == LW_SHAPE_FAT) {
804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            /* The lock has been fattened already.
805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                             */
806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            LOG_THIN("(%d) lock 0x%08x surprise-fattened\n",
807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                     threadId, (uint)&obj->lock);
808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            dvmChangeStatus(self, oldStatus);
809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            goto fat_lock;
810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        }
811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        if (sleepDelay == 0) {
813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            sched_yield();
814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            sleepDelay = 1 * 1000;
815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        } else {
816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            usleep(sleepDelay);
817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            if (sleepDelay < maxSleepDelay / 2) {
818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                sleepDelay *= 2;
819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            }
820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        }
821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
82294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro                    thin = threadId << LW_LOCK_OWNER_SHIFT;
8238d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro                    thin |= LW_HASH_STATE(*thinp) << LW_HASH_STATE_SHIFT;
824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } while (!ATOMIC_CMP_SWAP((int32_t *)thinp,
825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                          (int32_t)DVM_LOCK_INITIAL_THIN_VALUE,
82694338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro                                          (int32_t)thin));
827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_THIN("(%d) spin on lock done 0x%08x: "
828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         "0x%08x (0x%08x) 0x%08x\n",
829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         threadId, (uint)&obj->lock,
83094338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro                         DVM_LOCK_INITIAL_THIN_VALUE, *thinp, thin);
831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* We've got the thin lock; let the VM know that we're
833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * done waiting.
834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmChangeStatus(self, oldStatus);
836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* Fatten the lock.  Note this relinquishes ownership.
838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * We could also create the monitor in an "owned" state
839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * to avoid "re-locking" it in fat_lock.
840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
84194338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro                mon = dvmCreateMonitor(obj);
8428d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro                hashState = LW_HASH_STATE(*thinp) << LW_HASH_STATE_SHIFT;
8438d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro                obj->lock = (u4)mon | hashState | LW_SHAPE_FAT;
844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_THIN("(%d) lock 0x%08x fattened\n",
845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         threadId, (uint)&obj->lock);
846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* Fall through to acquire the newly fat lock.
848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* The lock is already fat, which means
8528d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro             * that obj->lock is a regular (Monitor *).
853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fat_lock:
8558d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro            assert(LW_MONITOR(obj->lock) != NULL);
8568d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro            lockMonitor(self, LW_MONITOR(obj->lock));
857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // else, the lock was acquired with the ATOMIC_CMP_SWAP().
860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * See if we were allowed to grab the lock at this time.  We do it
864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * *after* acquiring the lock, rather than before, so that we can
865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * freely update the Monitor struct.  This seems counter-intuitive,
866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * but our goal is deadlock *prediction* not deadlock *prevention*.
867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (If we actually deadlock, the situation is easy to diagnose from
868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * a thread dump, so there's no point making a special effort to do
869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the checks before the lock is held.)
870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * This needs to happen before we add the object to the thread's
872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * monitor list, so we can tell the difference between first-lock and
873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * re-lock.
874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * It's also important that we do this while in THREAD_RUNNING, so
876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that we don't interfere with cleanup operations in the GC.
877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.deadlockPredictMode != kDPOff) {
879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (self->status != THREAD_RUNNING) {
880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Bad thread status (%d) in DP\n", self->status);
881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmDumpThread(self, false);
882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!dvmCheckException(self));
885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        updateDeadlockPrediction(self, obj);
886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmCheckException(self)) {
887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * If we're throwing an exception here, we need to free the
889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * lock.  We add the object to the thread's monitor list so the
890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * "unlock" code can remove it.
891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAddToMonitorList(self, obj, false);
893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmUnlockObject(self, obj);
894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGV("--- unlocked, pending is '%s'\n",
895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmGetException(self)->clazz->descriptor);
896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Add the locked object, and the current stack trace, to the list
901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * held by the Thread object.  If deadlock prediction isn't on,
902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * don't capture the stack trace.
903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmAddToMonitorList(self, obj, gDvm.deadlockPredictMode != kDPOff);
905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#elif defined(WITH_MONITOR_TRACKING)
906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Add the locked object to the list held by the Thread object.
908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmAddToMonitorList(self, obj, false);
910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Implements monitorexit for "synchronized" stuff.
915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * On failure, throws an exception and returns "false".
917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmUnlockObject(Thread* self, Object *obj)
919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
9208d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    volatile u4 *thinp = &obj->lock;
921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 threadId = self->threadId;
92294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    u4 thin;
923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Check the common case, where 'self' has locked 'obj' once, first.
925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
92694338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    thin = *thinp;
92794338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    if (LW_LOCK_OWNER(thin) == threadId && LW_LOCK_COUNT(thin) == 0) {
928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Unlock 'obj' by clearing our threadId from 'thin'.
929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The lock protects the lock field itself, so it's
930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * safe to update non-atomically.
931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
93294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        *thinp &= (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT);
93394338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    } else if (LW_SHAPE(*thinp) == LW_SHAPE_THIN) {
934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* If the object is locked, it had better be locked by us.
935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
93694338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        if (LW_LOCK_OWNER(*thinp) != threadId) {
937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* The JNI spec says that we should throw an exception
938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * in this case.
939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //LOGW("Unlock thin %p: id %d vs %d\n",
941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //    obj, (*thinp & 0xfff), threadId);
942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "unlock of unowned monitor");
944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* It's a thin lock, but 'self' has locked 'obj'
948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * more than once.  Decrement the count.
949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
95094338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        *thinp -= 1 << LW_LOCK_COUNT_SHIFT;
951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* It's a fat lock.
953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
9548d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        assert(LW_MONITOR(obj->lock) != NULL);
9558d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        if (!unlockMonitor(self, LW_MONITOR(obj->lock))) {
956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* exception has been raised */
957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_MONITOR_TRACKING
962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Remove the object from the Thread's list.
964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmRemoveFromMonitorList(self, obj);
966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Object.wait().  Also called for class init.
973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmObjectWait(Thread* self, Object *obj, s8 msec, s4 nsec,
975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool interruptShouldThrow)
976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
9778d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    Monitor* mon = LW_MONITOR(obj->lock);
9788d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    u4 hashState;
9798d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    u4 thin = obj->lock;
980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* If the lock is still thin, we need to fatten it.
982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
98394338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Make sure that 'self' holds the lock.
985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
98694338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        if (LW_LOCK_OWNER(thin) != self->threadId) {
987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "object not locked by thread before wait()");
989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* This thread holds the lock.  We need to fatten the lock
993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * so 'self' can block on it.  Don't update the object lock
994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * field yet, because 'self' needs to acquire the lock before
995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * any other thread gets a chance.
996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon = dvmCreateMonitor(obj);
998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* 'self' has actually locked the object one or more times;
1000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * make sure that the monitor reflects this.
1001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        lockMonitor(self, mon);
100394338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        mon->lockCount = LW_LOCK_COUNT(thin);
1004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_THIN("(%d) lock 0x%08x fattened by wait() to count %d\n",
1005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 self->threadId, (uint)&obj->lock, mon->lockCount);
1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1007581bed77d3596b9d7242da10867c8d4cfd382239Andy McFadden
1008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Make the monitor public now that it's in the right state.
1009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1010581bed77d3596b9d7242da10867c8d4cfd382239Andy McFadden        MEM_BARRIER();
10118d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        hashState = LW_HASH_STATE(thin) << LW_HASH_STATE_SHIFT;
10128d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        obj->lock = (u4)mon | hashState | LW_SHAPE_FAT;
1013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    waitMonitor(self, mon, msec, nsec, interruptShouldThrow);
1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Object.notify().
1020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmObjectNotify(Thread* self, Object *obj)
1022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
10238d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    u4 thin = obj->lock;
1024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* If the lock is still thin, there aren't any waiters;
1026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * waiting on an object forces lock fattening.
1027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
102894338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
1029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Make sure that 'self' holds the lock.
1030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
103194338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        if (LW_LOCK_OWNER(thin) != self->threadId) {
1032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
1033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "object not locked by thread before notify()");
1034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
1035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* no-op;  there are no waiters to notify.
1038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* It's a fat lock.
1041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
104294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        notifyMonitor(self, LW_MONITOR(thin));
1043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Object.notifyAll().
1048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmObjectNotifyAll(Thread* self, Object *obj)
1050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
10518d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    u4 thin = obj->lock;
1052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* If the lock is still thin, there aren't any waiters;
1054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * waiting on an object forces lock fattening.
1055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
105694338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
1057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Make sure that 'self' holds the lock.
1058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
105994338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        if (LW_LOCK_OWNER(thin) != self->threadId) {
1060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
1061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "object not locked by thread before notifyAll()");
1062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
1063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* no-op;  there are no waiters to notify.
1066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* It's a fat lock.
1069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
107094338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        notifyAllMonitor(self, LW_MONITOR(thin));
1071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This implements java.lang.Thread.sleep(long msec, int nsec).
1076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The sleep is interruptible by other threads, which means we can't just
1078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * plop into an OS sleep call.  (We probably could if we wanted to send
1079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * signals around and rely on EINTR, but that's inefficient and relies
1080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * on native code respecting our signal mask.)
1081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We have to do all of this stuff for Object.wait() as well, so it's
1083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * easiest to just sleep on a private Monitor.
1084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It appears that we want sleep(0,0) to go through the motions of sleeping
1086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * for a very short duration, rather than just returning.
1087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmThreadSleep(u8 msec, u4 nsec)
1089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
1091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon = gDvm.threadSleepMon;
1092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* sleep(0,0) wakes up immediately, wait(0,0) means wait forever; adjust */
1094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (msec == 0 && nsec == 0)
1095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        nsec++;
1096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    lockMonitor(self, mon);
1098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    waitMonitor(self, mon, msec, nsec, true);
1099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unlockMonitor(self, mon);
1100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Implement java.lang.Thread.interrupt().
1104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We need to increment the monitor's "interrupting" count, and set the
1106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * interrupted status for the thread in question.  Doing so requires
1107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * gaining the monitor's lock, which may not happen in a timely fashion.
1108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We are left with a decision between failing to interrupt the thread
1109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and stalling the interrupting thread.
1110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We must take some care to ensure that we don't try to interrupt the same
1112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * thread on the same mutex twice.  Doing so would leave us with an
1113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * incorrect value for Monitor.interrupting.
1114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmThreadInterrupt(volatile Thread* thread)
1116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon;
1118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Raise the "interrupted" flag.  This will cause it to bail early out
1121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * of the next wait() attempt, if it's not currently waiting on
1122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * something.
1123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    thread->interrupted = true;
1125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MEM_BARRIER();
1126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Is the thread waiting?
1129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Note that fat vs. thin doesn't matter here;  waitMonitor
1131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * is only set when a thread actually waits on a monitor,
1132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * which implies that the monitor has already been fattened.
1133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon = thread->waitMonitor;
1135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon == NULL)
1136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Try to acquire the monitor, if we don't already own it.  We need
1140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * to hold the same mutex as the thread in order to signal the
1141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * condition it's waiting on.  When the thread goes to sleep it will
1142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * release the monitor's mutex, allowing us to signal it.
1143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * TODO: we may be able to get rid of the explicit lock by coordinating
1145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * this more closely with waitMonitor.
1146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
1148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!tryLockMonitor(self, mon)) {
1149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Failed to get the monitor the thread is waiting on; most likely
1151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * the other thread is in the middle of doing something.
1152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const int kSpinSleepTime = 500*1000;        /* 0.5s */
1154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u8 startWhen = dvmGetRelativeTimeUsec();
1155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int sleepIter = 0;
1156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        while (dvmIterativeSleep(sleepIter++, kSpinSleepTime, startWhen)) {
1158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
1159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Still time left on the clock, try to grab it again.
1160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (tryLockMonitor(self, mon))
1162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto gotit;
1163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
1165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * If the target thread is no longer waiting on the same monitor,
1166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * the "interrupted" flag we set earlier will have caused the
1167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * interrupt when the thread woke up, so we can stop now.
1168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (thread->waitMonitor != mon)
1170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return;
1171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We have to give up or risk deadlock.
1175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("threadid=%d: unable to interrupt threadid=%d\n",
1177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->threadId, thread->threadId);
1178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectgotit:
1182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We've got the monitor lock, which means nobody can be added or
1184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * removed from the wait list.  This also means that the Thread's
1185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * waitMonitor/interruptingWait fields can't be modified by anyone
1186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * else.
1187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If things look good, raise flags and wake the threads sleeping
1189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * on the monitor's condition variable.
1190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (thread->waitMonitor == mon &&       // still on same monitor?
1192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        thread->interrupted &&              // interrupt still pending?
1193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        !thread->interruptingWait)          // nobody else is interrupting too?
1194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
1195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int cc;
1196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("threadid=%d: interrupting threadid=%d waiting on %p\n",
1198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->threadId, thread->threadId, mon);
1199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        thread->interruptingWait = true;    // prevent re-interrupt...
1201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon->interrupting++;                // ...so we only do this once
1202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cc = pthread_cond_broadcast(&mon->cond);
1203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(cc == 0);
1204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unlockMonitor(self, mon);
1207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
120994338aadf8355b28846f0d21c49142ca29479dc4Carl Shapirou4 dvmIdentityHashCode(Object *obj)
121094338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro{
121194338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    return (u4)obj;
121294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro}
1213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
1215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
1217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Deadlock prediction
1218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
1219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe idea is to predict the possibility of deadlock by recording the order
1222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectin which monitors are acquired.  If we see an attempt to acquire a lock
1223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectout of order, we can identify the locks and offending code.
1224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectTo make this work, we need to keep track of the locks held by each thread,
1226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectand create history trees for each lock.  When a thread tries to acquire
1227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecta new lock, we walk through the "history children" of the lock, looking
1228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfor a match with locks the thread already holds.  If we find a match,
1229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectit means the thread has made a request that could result in a deadlock.
1230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectTo support recursive locks, we always allow re-locking a currently-held
1232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectlock, and maintain a recursion depth count.
1233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectAn ASCII-art example, where letters represent Objects:
1235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        A
1237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project       /|\
1238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project      / | \
1239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     B  |  D
1240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project      \ |
1241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project       \|
1242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        C
1243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe above is the tree we'd have after handling Object synchronization
1245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsequences "ABC", "AC", "AD".  A has three children, {B, C, D}.  C is also
1246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecta child of B.  (The lines represent pointers between parent and child.
1247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectEvery node can have multiple parents and multiple children.)
1248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectIf we hold AC, and want to lock B, we recursively search through B's
1250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchildren to see if A or C appears.  It does, so we reject the attempt.
1251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project(A straightforward way to implement it: add a link from C to B, then
1252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectdetermine whether the graph starting at B contains a cycle.)
1253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectIf we hold AC and want to lock D, we would succeed, creating a new link
1255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfrom C to D.
1256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe lock history and a stack trace is attached to the Object's Monitor
1258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstruct, which means we need to fatten every Object we lock (thin locking
1259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectis effectively disabled).  If we don't need the stack trace we can
1260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectavoid fattening the leaf nodes, only fattening objects that need to hold
1261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecthistory trees.
1262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectUpdates to Monitor structs are only allowed for the thread that holds
1264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe Monitor, so we actually do most of our deadlock prediction work after
1265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe lock has been acquired.
1266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectWhen an object with a monitor is GCed, we need to remove it from the
1268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecthistory trees.  There are two basic approaches:
1269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (1) For through the entire set of known monitors, search all child
1270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     lists for the object in question.  This is rather slow, resulting
1271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     in GC passes that take upwards of 10 seconds to complete.
1272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (2) Maintain "parent" pointers in each node.  Remove the entries as
1273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     required.  This requires additional storage and maintenance for
1274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     every operation, but is significantly faster at GC time.
1275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectFor each GCed object, we merge all of the object's children into each of
1276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe object's parents.
1277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project*/
1278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if !defined(WITH_MONITOR_TRACKING)
1280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# error "WITH_DEADLOCK_PREDICTION requires WITH_MONITOR_TRACKING"
1281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Clear out the contents of an ExpandingObjectList, freeing any
1285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * dynamic allocations.
1286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void expandObjClear(ExpandingObjectList* pList)
1288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pList->list != NULL) {
1290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(pList->list);
1291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pList->list = NULL;
1292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pList->alloc = pList->count = 0;
1294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the number of objects currently stored in the list.
1298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline int expandBufGetCount(const ExpandingObjectList* pList)
1300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return pList->count;
1302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the Nth entry from the list.
1306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline Object* expandBufGetEntry(const ExpandingObjectList* pList,
1308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i)
1309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return pList->list[i];
1311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add a new entry to the list.
1315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We don't check for or try to enforce uniqueness.  It's expected that
1317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the higher-level code does this for us.
1318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void expandObjAddEntry(ExpandingObjectList* pList, Object* obj)
1320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pList->count == pList->alloc) {
1322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* time to expand */
1323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object** newList;
1324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pList->alloc == 0)
1326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pList->alloc = 4;
1327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
1328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pList->alloc *= 2;
1329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("expanding %p to %d\n", pList, pList->alloc);
1330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newList = realloc(pList->list, pList->alloc * sizeof(Object*));
1331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (newList == NULL) {
1332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Failed expanding DP object list (alloc=%d)\n", pList->alloc);
1333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
1334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pList->list = newList;
1336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pList->list[pList->count++] = obj;
1339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if the element was successfully removed.
1343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool expandObjRemoveEntry(ExpandingObjectList* pList, Object* obj)
1345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = pList->count-1; i >= 0; i--) {
1349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pList->list[i] == obj)
1350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (i < 0)
1353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
1354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (i != pList->count-1) {
1356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The order of elements is not important, so we just copy the
1358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * last entry into the new slot.
1359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //memmove(&pList->list[i], &pList->list[i+1],
1361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    (pList->count-1 - i) * sizeof(pList->list[0]));
1362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pList->list[i] = pList->list[pList->count-1];
1363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pList->count--;
1366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pList->list[pList->count] = (Object*) 0xdecadead;
1367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
1368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if "obj" appears in the list.
1372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool expandObjHas(const ExpandingObjectList* pList, Object* obj)
1374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < pList->count; i++) {
1378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pList->list[i] == obj)
1379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
1380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return false;
1382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Print the list contents to stdout.  For debugging.
1386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void expandObjDump(const ExpandingObjectList* pList)
1388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < pList->count; i++)
1391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(" %p", pList->list[i]);
1392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Check for duplicate entries.  Returns the index of the first instance
1396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of the duplicated value, or -1 if no duplicates were found.
1397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int expandObjCheckForDuplicates(const ExpandingObjectList* pList)
1399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i, j;
1401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < pList->count-1; i++) {
1402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (j = i + 1; j < pList->count; j++) {
1403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (pList->list[i] == pList->list[j]) {
1404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return i;
1405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return -1;
1410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Determine whether "child" appears in the list of objects associated
1415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * with the Monitor in "parent".  If "parent" is a thin lock, we return
1416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * false immediately.
1417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool objectInChildList(const Object* parent, Object* child)
1419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
14208d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    u4 lock = parent->lock;
1421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!IS_LOCK_FAT(&lock)) {
1422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //LOGI("on thin\n");
1423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
1424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
14268d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    return expandObjHas(&LW_MONITOR(lock)->historyChildren, child);
1427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Print the child list.
1431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void dumpKids(Object* parent)
1433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
14348d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    Monitor* mon = LW_MONITOR(parent->lock);
1435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("Children of %p:", parent);
1437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    expandObjDump(&mon->historyChildren);
1438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("\n");
1439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add "child" to the list of children in "parent", and add "parent" to
1443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the list of parents in "child".
1444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void linkParentToChild(Object* parent, Object* child)
1446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
14478d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    //assert(LW_MONITOR(parent->lock)->owner == dvmThreadSelf());   // !owned for merge
1448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&parent->lock));
1449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&child->lock));
1450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(parent != child);
1451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon;
1452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
14538d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    mon = LW_MONITOR(parent->lock);
1454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!expandObjHas(&mon->historyChildren, child));
1455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    expandObjAddEntry(&mon->historyChildren, child);
1456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
14578d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    mon = LW_MONITOR(child->lock);
1458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!expandObjHas(&mon->historyParents, parent));
1459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    expandObjAddEntry(&mon->historyParents, parent);
1460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Remove "child" from the list of children in "parent".
1465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void unlinkParentFromChild(Object* parent, Object* child)
1467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
14688d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    //assert(LW_MONITOR(parent->lock)->owner == dvmThreadSelf());   // !owned for GC
1469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&parent->lock));
1470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&child->lock));
1471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(parent != child);
1472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon;
1473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
14748d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    mon = LW_MONITOR(parent->lock);
1475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!expandObjRemoveEntry(&mon->historyChildren, child)) {
1476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("WARNING: child %p not found in parent %p\n", child, parent);
1477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!expandObjHas(&mon->historyChildren, child));
1479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(expandObjCheckForDuplicates(&mon->historyChildren) < 0);
1480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
14818d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    mon = LW_MONITOR(child->lock);
1482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!expandObjRemoveEntry(&mon->historyParents, parent)) {
1483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("WARNING: parent %p not found in child %p\n", parent, child);
1484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!expandObjHas(&mon->historyParents, parent));
1486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(expandObjCheckForDuplicates(&mon->historyParents) < 0);
1487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Log the monitors held by the current thread.  This is done as part of
1492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * flagging an error.
1493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void logHeldMonitors(Thread* self)
1495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* name = NULL;
1497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    name = dvmGetThreadName(self);
1499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGW("Monitors currently held by thread (threadid=%d '%s')\n",
1500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        self->threadId, name);
1501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGW("(most-recently-acquired on top):\n");
1502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(name);
1503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LockedObjectData* lod = self->pLockedObjects;
1505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (lod != NULL) {
1506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("--- object %p[%d] (%s)\n",
1507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lod->obj, lod->recursionCount, lod->obj->clazz->descriptor);
1508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLogRawStackTrace(lod->rawStackTrace, lod->stackDepth);
1509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        lod = lod->next;
1511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Recursively traverse the object hierarchy starting at "obj".  We mark
1516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ourselves on entry and clear the mark on exit.  If we ever encounter
1517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a marked object, we have a cycle.
1518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if all is well, "false" if we found a cycle.
1520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool traverseTree(Thread* self, const Object* obj)
1522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&obj->lock));
15248d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    Monitor* mon = LW_MONITOR(obj->lock);
1525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Have we been here before?
1528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon->historyMark) {
1530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int* rawStackTrace;
1531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int stackDepth;
1532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("%s\n", kStartBanner);
1534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("Illegal lock attempt:\n");
1535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("--- object %p (%s)\n", obj, obj->clazz->descriptor);
1536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        rawStackTrace = dvmFillInStackTraceRaw(self, &stackDepth);
1538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLogRawStackTrace(rawStackTrace, stackDepth);
1539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(rawStackTrace);
1540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW(" ");
1542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        logHeldMonitors(self);
1543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW(" ");
1545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("Earlier, the following lock order (from last to first) was\n");
1546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("established -- stack trace is from first successful lock):\n");
1547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
1548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->historyMark = true;
1550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Examine the children.  We do NOT hold these locks, so they might
1553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * very well transition from thin to fat or change ownership while
1554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we work.
1555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * NOTE: we rely on the fact that they cannot revert from fat to thin
1557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * while we work.  This is currently a safe assumption.
1558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We can safely ignore thin-locked children, because by definition
1560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * they have no history and are leaf nodes.  In the current
1561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * implementation we always fatten the locks to provide a place to
1562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * hang the stack trace.
1563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExpandingObjectList* pList = &mon->historyChildren;
1565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
1567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const Object* child = expandBufGetEntry(pList, i);
15688d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        u4 lock = child->lock;
1569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!IS_LOCK_FAT(&lock))
1570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            continue;
1571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!traverseTree(self, child)) {
1572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("--- object %p (%s)\n", obj, obj->clazz->descriptor);
1573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLogRawStackTrace(mon->historyRawStackTrace,
1574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                mon->historyStackDepth);
1575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mon->historyMark = false;
1576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
1577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->historyMark = false;
1581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
1583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Update the deadlock prediction tree, based on the current thread
1587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * acquiring "acqObj".  This must be called before the object is added to
1588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the thread's list of held monitors.
1589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the thread already holds the lock (recursion), or this is a known
1591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * lock configuration, we return without doing anything.  Otherwise, we add
1592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a link from the most-recently-acquired lock in this thread to "acqObj"
1593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * after ensuring that the parent lock is "fat".
1594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This MUST NOT be called while a GC is in progress in another thread,
1596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because we assume exclusive access to history trees in owned monitors.
1597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void updateDeadlockPrediction(Thread* self, Object* acqObj)
1599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LockedObjectData* lod;
1601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LockedObjectData* mrl;
1602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Quick check for recursive access.
1605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    lod = dvmFindInMonitorList(self, acqObj);
1607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (lod != NULL) {
1608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("+++ DP: recursive %p\n", acqObj);
1609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Make the newly-acquired object's monitor "fat".  In some ways this
1614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * isn't strictly necessary, but we need the GC to tell us when
1615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * "interesting" objects go away, and right now the only way to make
1616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * an object look interesting is to give it a monitor.
1617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * This also gives us a place to hang a stack trace.
1619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Our thread holds the lock, so we're allowed to rewrite the lock
1621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * without worrying that something will change out from under us.
1622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!IS_LOCK_FAT(&acqObj->lock)) {
1624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("fattening lockee %p (recur=%d)\n",
162594338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro            acqObj, LW_LOCK_COUNT(acqObj->lock.thin));
1626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Monitor* newMon = dvmCreateMonitor(acqObj);
1627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        lockMonitor(self, newMon);      // can't stall, don't need VMWAIT
16288d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        newMon->lockCount += LW_LOCK_COUNT(acqObj->lock);
16298d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        u4 hashState = LW_HASH_STATE(acqObj->lock) << LW_HASH_STATE_SHIFT;
16308d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        acqObj->lock = (u4)newMon | hashState | LW_SHAPE_FAT;
1631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* if we don't have a stack trace for this monitor, establish one */
16348d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    if (LW_MONITOR(acqObj->lock)->historyRawStackTrace == NULL) {
16358d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        Monitor* mon = LW_MONITOR(acqObj->lock);
1636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon->historyRawStackTrace = dvmFillInStackTraceRaw(self,
1637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            &mon->historyStackDepth);
1638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We need to examine and perhaps modify the most-recently-locked
1642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * monitor.  We own that, so there's no risk of another thread
1643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * stepping on us.
1644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Retrieve the most-recently-locked entry from our thread.
1646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mrl = self->pLockedObjects;
1648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mrl == NULL)
1649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;         /* no other locks held */
1650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Do a quick check to see if "acqObj" is a direct descendant.  We can do
1653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * this without holding the global lock because of our assertion that
1654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * a GC is not running in parallel -- nobody except the GC can
1655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * modify a history list in a Monitor they don't own, and we own "mrl".
1656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (There might be concurrent *reads*, but no concurrent *writes.)
1657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If we find it, this is a known good configuration, and we're done.
1659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (objectInChildList(mrl->obj, acqObj))
1661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * "mrl" is going to need to have a history tree.  If it's currently
1665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * a thin lock, we make it fat now.  The thin lock might have a
1666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * nonzero recursive lock count, which we need to carry over.
1667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Our thread holds the lock, so we're allowed to rewrite the lock
1669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * without worrying that something will change out from under us.
1670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!IS_LOCK_FAT(&mrl->obj->lock)) {
1672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("fattening parent %p f/b/o child %p (recur=%d)\n",
16738d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro            mrl->obj, acqObj, LW_LOCK_COUNT(mrl->obj->lock));
1674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Monitor* newMon = dvmCreateMonitor(mrl->obj);
1675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        lockMonitor(self, newMon);      // can't stall, don't need VMWAIT
16768d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        newMon->lockCount += LW_LOCK_COUNT(mrl->obj->lock);
16778d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        u4 hashState = LW_HASH_STATE(mrl->obj->lock) << LW_HASH_STATE_SHIFT;
16788d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        mrl->obj->lock = (u4)newMon | hashState | LW_SHAPE_FAT;
1679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We haven't seen this configuration before.  We need to scan down
1683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * acqObj's tree to see if any of the monitors in self->pLockedObjects
1684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * appear.  We grab a global lock before traversing or updating the
1685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * history list.
1686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If we find a match for any of our held locks, we know that the lock
1688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * has previously been acquired *after* acqObj, and we throw an error.
1689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The easiest way to do this is to create a link from "mrl" to "acqObj"
1691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * and do a recursive traversal, marking nodes as we cross them.  If
1692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we cross one a second time, we have a cycle and can throw an error.
1693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (We do the flag-clearing traversal before adding the new link, so
1694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that we're guaranteed to terminate.)
1695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If "acqObj" is a thin lock, it has no history, and we can create a
1697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * link to it without additional checks.  [ We now guarantee that it's
1698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * always fat. ]
1699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool failed = false;
1701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLockMutex(&gDvm.deadlockHistoryLock);
1702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    linkParentToChild(mrl->obj, acqObj);
1703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!traverseTree(self, acqObj)) {
1704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("%s\n", kEndBanner);
1705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        failed = true;
1706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* remove the entry so we're still okay when in "warning" mode */
1708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unlinkParentFromChild(mrl->obj, acqObj);
1709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmUnlockMutex(&gDvm.deadlockHistoryLock);
1711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (failed) {
1713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (gDvm.deadlockPredictMode) {
1714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kDPErr:
1715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ldalvik/system/PotentialDeadlockError;", NULL);
1716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kDPAbort:
1718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Aborting due to potential deadlock\n");
1719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
1720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        default:
1722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* warn only */
1723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're removing "child" from existence.  We want to pull all of
1730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * child's children into "parent", filtering out duplicates.  This is
1731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * called during the GC.
1732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This does not modify "child", which might have multiple parents.
1734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void mergeChildren(Object* parent, const Object* child)
1736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon;
1738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&child->lock));
17418d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    mon = LW_MONITOR(child->lock);
1742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExpandingObjectList* pList = &mon->historyChildren;
1743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
1745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* grandChild = expandBufGetEntry(pList, i);
1746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!objectInChildList(parent, grandChild)) {
1748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGVV("+++  migrating %p link to %p\n", grandChild, parent);
1749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            linkParentToChild(parent, grandChild);
1750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGVV("+++  parent %p already links to %p\n", parent, grandChild);
1752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * An object with a fat lock is being collected during a GC pass.  We
1758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * want to remove it from any lock history trees that it is a part of.
1759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This may require updating the history trees in several monitors.  The
1761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * monitor semantics guarantee that no other thread will be accessing
1762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the history trees at the same time.
1763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void removeCollectedObject(Object* obj)
1765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon;
1767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("+++ collecting %p\n", obj);
1769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
1771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We're currently running through the entire set of known monitors.
1773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * This can be somewhat slow.  We may want to keep lists of parents
1774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in each child to speed up GC.
1775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon = gDvm.monitorList;
1777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (mon != NULL) {
1778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* parent = mon->obj;
1779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (parent != NULL) {       /* value nulled for deleted entries */
1780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (objectInChildList(parent, obj)) {
1781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGVV("removing child %p from parent %p\n", obj, parent);
1782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                unlinkParentFromChild(parent, obj);
1783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                mergeChildren(parent, obj);
1784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon = mon->next;
1787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * For every parent of this object:
1792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  - merge all of our children into the parent's child list (creates
1793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *    a two-way link between parent and child)
1794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  - remove ourselves from the parent's child list
1795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExpandingObjectList* pList;
1797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&obj->lock));
18008d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    mon = LW_MONITOR(obj->lock);
1801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pList = &mon->historyParents;
1802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
1803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* parent = expandBufGetEntry(pList, i);
18048d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        Monitor* parentMon = LW_MONITOR(parent->lock);
1805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!expandObjRemoveEntry(&parentMon->historyChildren, obj)) {
1807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("WARNING: child %p not found in parent %p\n", obj, parent);
1808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!expandObjHas(&parentMon->historyChildren, obj));
1810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mergeChildren(parent, obj);
1812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * For every child of this object:
1816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  - remove ourselves from the child's parent list
1817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pList = &mon->historyChildren;
1819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
1820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* child = expandBufGetEntry(pList, i);
18218d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        Monitor* childMon = LW_MONITOR(child->lock);
1822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!expandObjRemoveEntry(&childMon->historyParents, obj)) {
1824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("WARNING: parent %p not found in child %p\n", obj, child);
1825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!expandObjHas(&childMon->historyParents, obj));
1827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif /*WITH_DEADLOCK_PREDICTION*/
1831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1832