Sync.cpp revision b31b30131bbf58280a515c40027aa958b81b5cd6
1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16581bed77d3596b9d7242da10867c8d4cfd382239Andy McFadden
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Fundamental synchronization mechanisms.
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The top part of the file has operations on "monitor" structs; the
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * next part has the native calls on objects.
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The current implementation uses "thin locking" to avoid allocating
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an Object's full Monitor struct until absolutely necessary (i.e.,
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * during contention or a call to wait()).
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: make improvements to thin locking
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We may be able to improve performance and reduce memory requirements by:
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  - reverting to a thin lock once the Monitor is no longer necessary
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  - using a pool of monitor objects, with some sort of recycling scheme
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: recycle native-level monitors when objects are garbage collected.
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h"
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
36f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro#include <fcntl.h>
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h>
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <unistd.h>
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <pthread.h>
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <time.h>
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <sys/time.h>
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <errno.h>
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define LOG_THIN    LOGV
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION     /* fwd */
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic const char* kStartBanner =
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "<-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#";
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic const char* kEndBanner =
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    "#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#->";
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unsorted, expanding list of objects.
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is very similar to PointerSet (which came into existence after this),
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * but these are unsorted, uniqueness is not enforced by the "add" function,
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and the base object isn't allocated on the heap.
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct ExpandingObjectList {
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u2          alloc;
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u2          count;
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object**    list;
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} ExpandingObjectList;
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* fwd */
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void updateDeadlockPrediction(Thread* self, Object* obj);
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void removeCollectedObject(Object* obj);
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void expandObjClear(ExpandingObjectList* pList);
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Every Object has a monitor associated with it, but not every Object is
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * actually locked.  Even the ones that are locked do not need a
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * full-fledged monitor until a) there is actual contention or b) wait()
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is called on the Object.
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For Dalvik, we have implemented a scheme similar to the one described
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in Bacon et al.'s "Thin locks: featherweight synchronization for Java"
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (ACM 1998).  Things are even easier for us, though, because we have
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a full 32 bits to work with.
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * The two states of an Object's lock are referred to as "thin" and
8394338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * "fat".  A lock may transition from the "thin" state to the "fat"
8494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * state and this transition is referred to as inflation.  Once a lock
8594338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * has been inflated it remains in the "fat" state indefinitely.
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * The lock value itself is stored in Object.lock.  The LSB of the
8877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * lock encodes its state.  When cleared, the lock is in the "thin"
8977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * state and its bits are formatted as follows:
9071938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro *
9194338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro *    [31 ---- 19] [18 ---- 3] [2 ---- 1] [0]
9294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro *     lock count   thread id  hash state  0
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
9477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * When set, the lock is in the "fat" state and its bits are formatted
9594338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro * as follows:
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
9794338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro *    [31 ---- 3] [2 ---- 1] [0]
9894338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro *      pointer   hash state  1
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For an in-depth description of the mechanics of thin-vs-fat locking,
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * read the paper referred to above.
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Monitors provide:
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  - mutually exclusive access to resources
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  - a way for multiple threads to wait for notification
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In effect, they fill the role of both mutexes and condition variables.
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Only one thread can own the monitor at any time.  There may be several
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * threads waiting on it (the wait call unlocks it).  One or more waiting
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * threads may be getting interrupted or notified at any given time.
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstruct Monitor {
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread*     owner;          /* which thread currently owns the lock? */
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int         lockCount;      /* owner's recursive lock depth */
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object*     obj;            /* what object are we part of [debug only] */
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
12077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    Thread*     waitSet;	/* threads currently waiting on this monitor */
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pthread_mutex_t lock;
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor*    next;
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Objects that have been locked immediately after this one in the
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * past.  We use an expanding flat array, allocated on first use, to
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * minimize allocations.  Deletions from the list, expected to be
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * infrequent, are crunched down.
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExpandingObjectList historyChildren;
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We also track parents.  This isn't strictly necessary, but it makes
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the cleanup at GC time significantly faster.
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExpandingObjectList historyParents;
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* used during cycle detection */
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool        historyMark;
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* stack trace, established the first time we locked the object */
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int         historyStackDepth;
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int*        historyRawStackTrace;
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project};
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create and initialize a monitor.
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectMonitor* dvmCreateMonitor(Object* obj)
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon;
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon = (Monitor*) calloc(1, sizeof(Monitor));
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon == NULL) {
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("Unable to allocate monitor\n");
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAbort();
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
16394338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    if (((u4)mon & 7) != 0) {
16494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        LOGE("Misaligned monitor: %p\n", mon);
16594338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        dvmAbort();
16694338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    }
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->obj = obj;
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmInitMutex(&mon->lock);
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* replace the head of the list with the new monitor */
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    do {
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon->next = gDvm.monitorList;
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } while (!ATOMIC_CMP_SWAP((int32_t*)(void*)&gDvm.monitorList,
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                              (int32_t)mon->next, (int32_t)mon));
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return mon;
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free the monitor list.  Only used when shutting the VM down.
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmFreeMonitorList(void)
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon;
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* nextMon;
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon = gDvm.monitorList;
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (mon != NULL) {
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        nextMon = mon->next;
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        expandObjClear(&mon->historyChildren);
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        expandObjClear(&mon->historyParents);
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(mon->historyRawStackTrace);
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(mon);
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon = nextMon;
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Log some info about our monitors.
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpMonitorInfo(const char* msg)
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if QUIET_ZYGOTE_MONITOR
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.zygote) {
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int totalCount;
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int liveCount;
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    totalCount = liveCount = 0;
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon = gDvm.monitorList;
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (mon != NULL) {
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        totalCount++;
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (mon->obj != NULL)
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            liveCount++;
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon = mon->next;
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGD("%s: monitor list has %d entries (%d live)\n",
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        msg, totalCount, liveCount);
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the object that a monitor is part of.
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectObject* dvmGetMonitorObject(Monitor* mon)
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon == NULL)
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return mon->obj;
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
24030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * Returns the thread id of the thread owning the given lock.
24130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */
24230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapirostatic u4 lockOwner(Object* obj)
24330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro{
24430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    Thread *owner;
24530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    u4 lock;
24630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro
24730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    assert(obj != NULL);
24830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    /*
24930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro     * Since we're reading the lock value multiple times, latch it so
25030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro     * that it doesn't change out from under us if we get preempted.
25130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro     */
25230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    lock = obj->lock;
25330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    if (LW_SHAPE(lock) == LW_SHAPE_THIN) {
25430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        return LW_LOCK_OWNER(lock);
25530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    } else {
25630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        owner = LW_MONITOR(lock)->owner;
25730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        return owner ? owner->threadId : 0;
25830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    }
25930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro}
26030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro
26130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro/*
262fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * Get the thread that holds the lock on the specified object.  The
263fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * object may be unlocked, thin-locked, or fat-locked.
264fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden *
265fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * The caller must lock the thread list before calling here.
266fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden */
267fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFaddenThread* dvmGetObjectLockHolder(Object* obj)
268fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden{
269fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    u4 threadId = lockOwner(obj);
270fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden
271fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    if (threadId == 0)
272fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden        return NULL;
273fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    return dvmGetThreadByThreadId(threadId);
274fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden}
275fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden
276fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden/*
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Checks whether the given thread holds the given
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * objects's lock.
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmHoldsLock(Thread* thread, Object* obj)
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (thread == NULL || obj == NULL) {
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
28530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        return thread->threadId == lockOwner(obj);
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free the monitor associated with an object and make the object's lock
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * thin again.  This is called during garbage collection.
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2935a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapirostatic void freeObjectMonitor(Object* obj)
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor *mon;
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2975a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    assert(LW_SHAPE(obj->lock) == LW_SHAPE_FAT);
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.deadlockPredictMode != kDPOff)
3015a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro        removeCollectedObject(obj);
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3045a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    mon = LW_MONITOR(obj->lock);
3055a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    obj->lock = DVM_LOCK_INITIAL_THIN_VALUE;
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* This lock is associated with an object
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that's being swept.  The only possible way
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * anyone could be holding this lock would be
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * if some JNI code locked but didn't unlock
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the object, in which case we've got some bad
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * native code somewhere.
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3141ff876da3c8316ebe4a39e29b5db697953421511Carl Shapiro    assert(pthread_mutex_trylock(&mon->lock) == 0);
3151ff876da3c8316ebe4a39e29b5db697953421511Carl Shapiro    assert(pthread_mutex_unlock(&mon->lock) == 0);
316980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro    dvmDestroyMutex(&mon->lock);
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
3185a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    expandObjClear(&mon->historyChildren);
3195a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    expandObjClear(&mon->historyParents);
3205a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    free(mon->historyRawStackTrace);
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
3225a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    free(mon);
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3255a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro/*
3265a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro * Frees monitor objects belonging to unmarked objects.
3275a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro */
3285a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapirovoid dvmSweepMonitorList(Monitor** mon, int (*isUnmarkedObject)(void*))
3295a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro{
3305a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    Monitor handle;
3315a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    Monitor *prev, *curr;
3325a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    Object *obj;
3335a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro
3345a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    assert(mon != NULL);
3355a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    assert(isUnmarkedObject != NULL);
3365a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    prev = &handle;
3375a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    prev->next = curr = *mon;
3385a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    while (curr != NULL) {
3395a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro        obj = curr->obj;
3405a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro        if (obj != NULL && (*isUnmarkedObject)(obj) != 0) {
3415a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro            prev->next = curr = curr->next;
3425a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro            freeObjectMonitor(obj);
3435a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro        } else {
3445a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro            prev = curr;
3455a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro            curr = curr->next;
3465a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro        }
3475a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    }
3485a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro    *mon = handle.next;
3495a6071b914e7669eaf032256f163f65403bfcf3bCarl Shapiro}
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
351f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapirostatic char *logWriteInt(char *dst, int value)
352f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro{
353f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    *dst++ = EVENT_TYPE_INT;
354f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    set4LE((u1 *)dst, value);
355f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    return dst + 4;
356f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro}
357f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
358f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapirostatic char *logWriteString(char *dst, const char *value, size_t len)
359f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro{
360f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    *dst++ = EVENT_TYPE_STRING;
361af69cf8d062a42300852ddee6bcb9f189f5a1b83Carl Shapiro    len = len < 32 ? len : 32;
362f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    set4LE((u1 *)dst, len);
363f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    dst += 4;
364f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    memcpy(dst, value, len);
365f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    return dst + len;
366f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro}
367f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
368af69cf8d062a42300852ddee6bcb9f189f5a1b83Carl Shapiro#define EVENT_LOG_TAG_dvm_lock_sample 20003
369f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
370f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapirostatic void logContentionEvent(Thread *self, u4 waitMs, u4 samplePercent)
371f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro{
372f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    const StackSaveArea *saveArea;
373f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    const Method *meth;
374f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    u4 relativePc;
375af69cf8d062a42300852ddee6bcb9f189f5a1b83Carl Shapiro    char eventBuffer[132];
376f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    const char *fileName;
377e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro    char procName[33], *selfName;
378f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    char *cp;
379af69cf8d062a42300852ddee6bcb9f189f5a1b83Carl Shapiro    size_t len;
380af69cf8d062a42300852ddee6bcb9f189f5a1b83Carl Shapiro    int fd;
381f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
382f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    saveArea = SAVEAREA_FROM_FP(self->curFrame);
383f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    meth = saveArea->method;
384f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    cp = eventBuffer;
385f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
386f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    /* Emit the event list length, 1 byte. */
387f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    *cp++ = 7;
388f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
389f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    /* Emit the process name, <= 37 bytes. */
390f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    fd = open("/proc/self/cmdline", O_RDONLY);
391af69cf8d062a42300852ddee6bcb9f189f5a1b83Carl Shapiro    memset(procName, 0, sizeof(procName));
392af69cf8d062a42300852ddee6bcb9f189f5a1b83Carl Shapiro    read(fd, procName, sizeof(procName) - 1);
393f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    close(fd);
394af69cf8d062a42300852ddee6bcb9f189f5a1b83Carl Shapiro    len = strlen(procName);
395af69cf8d062a42300852ddee6bcb9f189f5a1b83Carl Shapiro    cp = logWriteString(cp, procName, len);
396f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
397f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    /* Emit the main thread status, 5 bytes. */
398f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    bool isMainThread = (self->systemTid == getpid());
399f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    cp = logWriteInt(cp, isMainThread);
400f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
401f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    /* Emit self thread name string, <= 37 bytes. */
402f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    selfName = dvmGetThreadName(self);
403f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    cp = logWriteString(cp, selfName, strlen(selfName));
404f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    free(selfName);
405f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
406f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    /* Emit the wait time, 5 bytes. */
407f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    cp = logWriteInt(cp, waitMs);
408f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
409f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    /* Emit the source code file name, <= 37 bytes. */
410f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    fileName = dvmGetMethodSourceFile(meth);
411f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    if (fileName == NULL) fileName = "";
412f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    cp = logWriteString(cp, fileName, strlen(fileName));
413f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
414f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    /* Emit the source code line number, 5 bytes. */
415f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    relativePc = saveArea->xtra.currentPc - saveArea->method->insns;
416f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    cp = logWriteInt(cp, dvmLineNumFromPC(meth, relativePc));
417f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
418f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    /* Emit the sample percentage, 5 bytes. */
419f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    cp = logWriteInt(cp, samplePercent);
420f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
421f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    assert((size_t)(cp - eventBuffer) <= sizeof(eventBuffer));
422af69cf8d062a42300852ddee6bcb9f189f5a1b83Carl Shapiro    android_btWriteLog(EVENT_LOG_TAG_dvm_lock_sample,
423f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro                       EVENT_TYPE_LIST,
424f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro                       eventBuffer,
425f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro                       (size_t)(cp - eventBuffer));
426f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro}
427f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Lock a monitor.
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void lockMonitor(Thread* self, Monitor* mon)
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
433f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    ThreadStatus oldStatus;
434f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    u4 waitThreshold, samplePercent;
435f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    u8 waitStart, waitEnd, waitMs;
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon->owner == self) {
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon->lockCount++;
439f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro        return;
440f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    }
441045fdc99f7c0dfde95002da66cb85ace19aee069Carl Shapiro    if (dvmTryLockMutex(&mon->lock) != 0) {
442f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro        oldStatus = dvmChangeStatus(self, THREAD_MONITOR);
443f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro        waitThreshold = gDvm.lockProfThreshold;
444f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro        if (waitThreshold) {
445f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro            waitStart = dvmGetRelativeTimeUsec();
446f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro        }
447f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro        dvmLockMutex(&mon->lock);
448f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro        if (waitThreshold) {
449f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro            waitEnd = dvmGetRelativeTimeUsec();
450f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro        }
451f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro        dvmChangeStatus(self, oldStatus);
452f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro        if (waitThreshold) {
453f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro            waitMs = (waitEnd - waitStart) / 1000;
454f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro            if (waitMs >= waitThreshold) {
455f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro                samplePercent = 100;
456f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro            } else {
457af69cf8d062a42300852ddee6bcb9f189f5a1b83Carl Shapiro                samplePercent = 100 * waitMs / waitThreshold;
458f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro            }
459b8fcf57f13b4d37950cfbd72a6af401941d7bdd8Carl Shapiro            if (samplePercent != 0 && ((u4)rand() % 100 < samplePercent)) {
460f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro                logContentionEvent(self, waitMs, samplePercent);
461f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro            }
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
464f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    mon->owner = self;
465f0c514ce8c64a441375af4a7e364282a3d803c45Carl Shapiro    assert(mon->lockCount == 0);
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Try to lock a monitor.
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" on success.
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
473b31b30131bbf58280a515c40027aa958b81b5cd6Carl Shapiro#ifdef WITH_COPYING_GC
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool tryLockMonitor(Thread* self, Monitor* mon)
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon->owner == self) {
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon->lockCount++;
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
480980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro        if (dvmTryLockMutex(&mon->lock) == 0) {
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mon->owner = self;
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(mon->lockCount == 0);
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
489b31b30131bbf58280a515c40027aa958b81b5cd6Carl Shapiro#endif
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unlock a monitor.
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns true if the unlock succeeded.
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the unlock failed, an exception will be pending.
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool unlockMonitor(Thread* self, Monitor* mon)
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
49977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(self != NULL);
5009227708d5de03fd72c8a99e3dd2747934591ba5bCarl Shapiro    assert(mon != NULL);
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon->owner == self) {
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We own the monitor, so nobody else can be in here.
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (mon->lockCount == 0) {
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mon->owner = NULL;
507980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro            dvmUnlockMutex(&mon->lock);
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mon->lockCount--;
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We don't own this, so we're not allowed to unlock it.
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The JNI spec says that we should throw IllegalMonitorStateException
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * in this case.
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
5178782d7ca2bce5ad097557afc3886c52bf85eb99fCarl Shapiro        dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
5188782d7ca2bce5ad097557afc3886c52bf85eb99fCarl Shapiro                          "unlock of unowned monitor");
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
52577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro * Checks the wait set for circular structure.  Returns 0 if the list
526b453919fee9bf10ccd576d389d8b3584061bba8bCarl Shapiro * is not circular.  Otherwise, returns 1.  Used only by asserts.
52777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro */
528b31b30131bbf58280a515c40027aa958b81b5cd6Carl Shapiro#ifndef NDEBUG
52977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapirostatic int waitSetCheck(Monitor *mon)
53077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro{
53177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    Thread *fast, *slow;
53277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    size_t n;
53377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
53477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(mon != NULL);
53577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    fast = slow = mon->waitSet;
53677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    n = 0;
53777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    for (;;) {
53877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        if (fast == NULL) return 0;
53977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        if (fast->waitNext == NULL) return 0;
5405f56e67999c67861872c27097803d2126142fed4Carl Shapiro        if (fast == slow && n > 0) return 1;
54177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        n += 2;
54277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        fast = fast->waitNext->waitNext;
54377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        slow = slow->waitNext;
54477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
54577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro}
546b31b30131bbf58280a515c40027aa958b81b5cd6Carl Shapiro#endif
54777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
54877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro/*
54930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * Links a thread into a monitor's wait set.  The monitor lock must be
55030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * held by the caller of this routine.
55177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro */
55277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapirostatic void waitSetAppend(Monitor *mon, Thread *thread)
55377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro{
55477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    Thread *elt;
55577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
55677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(mon != NULL);
55730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    assert(mon->owner == dvmThreadSelf());
55877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(thread != NULL);
55977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(thread->waitNext == NULL);
56077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(waitSetCheck(mon) == 0);
56177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (mon->waitSet == NULL) {
56277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        mon->waitSet = thread;
56377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        return;
56477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
56577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    elt = mon->waitSet;
56677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    while (elt->waitNext != NULL) {
56777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        elt = elt->waitNext;
56877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
56977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    elt->waitNext = thread;
57077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro}
57177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
57277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro/*
57330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * Unlinks a thread from a monitor's wait set.  The monitor lock must
57430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * be held by the caller of this routine.
57577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro */
57677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapirostatic void waitSetRemove(Monitor *mon, Thread *thread)
57777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro{
57877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    Thread *elt;
57977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
58077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(mon != NULL);
58130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    assert(mon->owner == dvmThreadSelf());
58277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(thread != NULL);
58377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(waitSetCheck(mon) == 0);
58477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (mon->waitSet == NULL) {
58577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        return;
58677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
58777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (mon->waitSet == thread) {
58877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        mon->waitSet = thread->waitNext;
58977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        thread->waitNext = NULL;
59077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        return;
59177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
59277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    elt = mon->waitSet;
59377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    while (elt->waitNext != NULL) {
59477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        if (elt->waitNext == thread) {
59577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro            elt->waitNext = thread->waitNext;
59677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro            thread->waitNext = NULL;
59777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro            return;
59877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        }
59977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        elt = elt->waitNext;
60077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
60177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro}
60277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
603b453919fee9bf10ccd576d389d8b3584061bba8bCarl Shapiro/*
604b453919fee9bf10ccd576d389d8b3584061bba8bCarl Shapiro * Converts the given relative waiting time into an absolute time.
605b453919fee9bf10ccd576d389d8b3584061bba8bCarl Shapiro */
606fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbeevoid absoluteTime(s8 msec, s4 nsec, struct timespec *ts)
60777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro{
60877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    s8 endSec;
60977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
61077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro#ifdef HAVE_TIMEDWAIT_MONOTONIC
61177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    clock_gettime(CLOCK_MONOTONIC, ts);
61277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro#else
61377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    {
61477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        struct timeval tv;
61577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        gettimeofday(&tv, NULL);
61677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        ts->tv_sec = tv.tv_sec;
61777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        ts->tv_nsec = tv.tv_usec * 1000;
61877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
61977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro#endif
62077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    endSec = ts->tv_sec + msec / 1000;
62177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (endSec >= 0x7fffffff) {
62277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        LOGV("NOTE: end time exceeds epoch\n");
62377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        endSec = 0x7ffffffe;
62477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
62577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    ts->tv_sec = endSec;
62677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    ts->tv_nsec = (ts->tv_nsec + (msec % 1000) * 1000000) + nsec;
62777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
62877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    /* catch rollover */
62977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (ts->tv_nsec >= 1000000000L) {
63077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        ts->tv_sec++;
63177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        ts->tv_nsec -= 1000000000L;
63277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
63377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro}
63477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
635fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbeeint dvmRelativeCondWait(pthread_cond_t* cond, pthread_mutex_t* mutex,
636fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee                        s8 msec, s4 nsec)
637fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee{
638fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee    int ret;
639fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee    struct timespec ts;
640fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee    absoluteTime(msec, nsec, &ts);
641fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee#if defined(HAVE_TIMEDWAIT_MONOTONIC)
642fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee    ret = pthread_cond_timedwait_monotonic(cond, mutex, &ts);
643fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee#else
644fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee    ret = pthread_cond_timedwait(cond, mutex, &ts);
645fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee#endif
646fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee    assert(ret == 0 || ret == ETIMEDOUT);
647fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee    return ret;
648fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee}
649fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee
65077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro/*
651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Wait on a monitor until timeout, interrupt, or notification.  Used for
652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Object.wait() and (somewhat indirectly) Thread.sleep() and Thread.join().
653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If another thread calls Thread.interrupt(), we throw InterruptedException
655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and return immediately if one of the following are true:
656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  - blocked in wait(), wait(long), or wait(long, int) methods of Object
657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  - blocked in join(), join(long), or join(long, int) methods of Thread
658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  - blocked in sleep(long), or sleep(long, int) methods of Thread
659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Otherwise, we set the "interrupted" flag.
660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Checks to make sure that "nsec" is in the range 0-999999
662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (i.e. fractions of a millisecond) and throws the appropriate
663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exception if it isn't.
664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The spec allows "spurious wakeups", and recommends that all code using
666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Object.wait() do so in a loop.  This appears to derive from concerns
667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * about pthread_cond_wait() on multiprocessor systems.  Some commentary
668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * on the web casts doubt on whether these can/should occur.
669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Since we're allowed to wake up "early", we clamp extremely long durations
671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to return at the end of the 32-bit time epoch.
672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void waitMonitor(Thread* self, Monitor* mon, s8 msec, s4 nsec,
674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool interruptShouldThrow)
675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct timespec ts;
677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool wasInterrupted = false;
678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool timed;
67977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    int ret;
680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
68171938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    assert(self != NULL);
68271938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    assert(mon != NULL);
68371938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro
68494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    /* Make sure that we hold the lock. */
68571938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    if (mon->owner != self) {
686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "object not locked by thread before wait()");
688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Enforce the timeout range.
693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (msec < 0 || nsec < 0 || nsec > 999999) {
695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/lang/IllegalArgumentException;",
696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "timeout arguments out of range");
697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Compute absolute wakeup time, if necessary.
702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (msec == 0 && nsec == 0) {
704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        timed = false;
705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
706fccb31dd58e5cb9f7a3f6e128d481f0ff35a51f0Bill Buzbee        absoluteTime(msec, nsec, &ts);
707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        timed = true;
708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Add ourselves to the set of threads waiting on this monitor, and
712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * release our hold.  We need to let it go even if we're a few levels
713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * deep in a recursive lock, and we need to restore that later.
714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
715142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapiro     * We append to the wait set ahead of clearing the count and owner
716142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapiro     * fields so the subroutine can check that the calling thread owns
717142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapiro     * the monitor.  Aside from that, the order of member updates is
718142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapiro     * not order sensitive as we hold the pthread mutex.
719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
720142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapiro    waitSetAppend(mon, self);
721142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapiro    int prevLockCount = mon->lockCount;
722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->lockCount = 0;
723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->owner = NULL;
724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Update thread status.  If the GC wakes up, it'll ignore us, knowing
727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that we won't touch any references in this state, and we'll check
728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * our suspend mode before we transition out.
729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (timed)
731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmChangeStatus(self, THREAD_TIMED_WAIT);
732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmChangeStatus(self, THREAD_WAIT);
734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
735980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro    dvmLockMutex(&self->waitMutex);
73677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
73877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     * Set waitMonitor to the monitor object we will be waiting on.
73977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     * When waitMonitor is non-NULL a notifying or interrupting thread
74077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     * must signal the thread's waitCond to wake it up.
741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
74277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(self->waitMonitor == NULL);
743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->waitMonitor = mon;
744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Handle the case where the thread was interrupted before we called
747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * wait().
748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (self->interrupted) {
750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        wasInterrupted = true;
75177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        self->waitMonitor = NULL;
752980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro        dvmUnlockMutex(&self->waitMutex);
753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto done;
754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
75677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    /*
75777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     * Release the monitor lock and wait for a notification or
75877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     * a timeout to occur.
75977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     */
760980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro    dvmUnlockMutex(&mon->lock);
76177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
76277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (!timed) {
76377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        ret = pthread_cond_wait(&self->waitCond, &self->waitMutex);
76477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        assert(ret == 0);
76577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    } else {
766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef HAVE_TIMEDWAIT_MONOTONIC
76777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        ret = pthread_cond_timedwait_monotonic(&self->waitCond, &self->waitMutex, &ts);
768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
76977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        ret = pthread_cond_timedwait(&self->waitCond, &self->waitMutex, &ts);
770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
77177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        assert(ret == 0 || ret == ETIMEDOUT);
77277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
77377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (self->interrupted) {
77477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        wasInterrupted = true;
775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
77777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    self->interrupted = false;
77877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    self->waitMonitor = NULL;
77977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
780980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro    dvmUnlockMutex(&self->waitMutex);
78177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
78230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    /* Reacquire the monitor lock. */
78377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    lockMonitor(self, mon);
784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
785142ef271a96b4bb2997effc3f3c1bfa601abbeb6Carl Shapirodone:
786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
78707b359273a838a15accafefcbe861be15caaac3aCarl Shapiro     * We remove our thread from wait set after restoring the count
78807b359273a838a15accafefcbe861be15caaac3aCarl Shapiro     * and owner fields so the subroutine can check that the calling
78907b359273a838a15accafefcbe861be15caaac3aCarl Shapiro     * thread owns the monitor. Aside from that, the order of member
79007b359273a838a15accafefcbe861be15caaac3aCarl Shapiro     * updates is not order sensitive as we hold the pthread mutex.
791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->owner = self;
793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->lockCount = prevLockCount;
79407b359273a838a15accafefcbe861be15caaac3aCarl Shapiro    waitSetRemove(mon, self);
795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* set self->status back to THREAD_RUNNING, and self-suspend if needed */
797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmChangeStatus(self, THREAD_RUNNING);
798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (wasInterrupted) {
800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We were interrupted while waiting, or somebody interrupted an
80230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * un-interruptible thread earlier and we're bailing out immediately.
803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The doc sayeth: "The interrupted status of the current thread is
805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * cleared when this exception is thrown."
806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        self->interrupted = false;
808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (interruptShouldThrow)
809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/InterruptedException;", NULL);
810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Notify one thread waiting on this monitor.
815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void notifyMonitor(Thread* self, Monitor* mon)
817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
81877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    Thread* thread;
81977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
82071938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    assert(self != NULL);
82171938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    assert(mon != NULL);
82271938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro
82394338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    /* Make sure that we hold the lock. */
82471938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    if (mon->owner != self) {
825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "object not locked by thread before notify()");
827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
82930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    /* Signal the first waiting thread in the wait set. */
83030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    while (mon->waitSet != NULL) {
83177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        thread = mon->waitSet;
83277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        mon->waitSet = thread->waitNext;
83377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        thread->waitNext = NULL;
834980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro        dvmLockMutex(&thread->waitMutex);
83577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        /* Check to see if the thread is still waiting. */
83677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        if (thread->waitMonitor != NULL) {
83777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro            pthread_cond_signal(&thread->waitCond);
838980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro            dvmUnlockMutex(&thread->waitMutex);
83930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            return;
84077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        }
841980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro        dvmUnlockMutex(&thread->waitMutex);
842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Notify all threads waiting on this monitor.
847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void notifyAllMonitor(Thread* self, Monitor* mon)
849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
85077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    Thread* thread;
85177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
85271938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    assert(self != NULL);
85371938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    assert(mon != NULL);
85471938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro
85594338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    /* Make sure that we hold the lock. */
85671938023ea2bacc1923ec44c71a797f254d268e2Carl Shapiro    if (mon->owner != self) {
857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "object not locked by thread before notifyAll()");
859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
86177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    /* Signal all threads in the wait set. */
86277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    while (mon->waitSet != NULL) {
86377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        thread = mon->waitSet;
86477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        mon->waitSet = thread->waitNext;
86577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        thread->waitNext = NULL;
866980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro        dvmLockMutex(&thread->waitMutex);
86777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        /* Check to see if the thread is still waiting. */
86877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        if (thread->waitMonitor != NULL) {
86977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro            pthread_cond_signal(&thread->waitCond);
87077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        }
871980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro        dvmUnlockMutex(&thread->waitMutex);
872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
87666bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro * Changes the shape of a monitor from thin to fat, preserving the
87766bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro * internal lock state.  The calling thread must own the lock.
87866bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro */
87966bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapirostatic void inflateMonitor(Thread *self, Object *obj)
88066bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro{
88166bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    Monitor *mon;
88266bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    u4 thin;
88366bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro
88466bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    assert(self != NULL);
88566bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    assert(obj != NULL);
88666bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    assert(LW_SHAPE(obj->lock) == LW_SHAPE_THIN);
88766bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    assert(LW_LOCK_OWNER(obj->lock) == self->threadId);
88866bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    /* Allocate and acquire a new monitor. */
88966bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    mon = dvmCreateMonitor(obj);
89066bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    lockMonitor(self, mon);
89166bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    /* Propagate the lock state. */
89266bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    thin = obj->lock;
89366bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    mon->lockCount = LW_LOCK_COUNT(thin);
89466bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    thin &= LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT;
89566bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    thin |= (u4)mon | LW_SHAPE_FAT;
89666bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    /* Publish the updated lock word. */
89766bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    MEM_BARRIER();
89866bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    obj->lock = thin;
89966bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro}
90066bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro
90166bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro/*
902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Implements monitorenter for "synchronized" stuff.
903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This does not fail or throw an exception (unless deadlock prediction
905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is enabled and set to "err" mode).
906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmLockObject(Thread* self, Object *obj)
908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
909147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    volatile u4 *thinp;
910147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    ThreadStatus oldStatus;
911147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    useconds_t sleepDelay;
912147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    const useconds_t maxSleepDelay = 1 << 20;
913147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    u4 thin, newThin, threadId;
914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
915147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    assert(self != NULL);
916147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    assert(obj != NULL);
917147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    threadId = self->threadId;
918147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    thinp = &obj->lock;
919147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiroretry:
920147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    thin = *thinp;
921147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
922147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro        /*
923147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro         * The lock is a thin lock.  The owner field is used to
924147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro         * determine the acquire method, ordered by cost.
925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
926147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro        if (LW_LOCK_OWNER(thin) == threadId) {
927147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            /*
928147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * The calling thread owns the lock.  Increment the
929147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * value of the recursion count field.
930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
931147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            obj->lock += 1 << LW_LOCK_COUNT_SHIFT;
932147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro        } else if (LW_LOCK_OWNER(thin) == 0) {
933147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            /*
934147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * The lock is unowned.  Install the thread id of the
935147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * calling thread into the owner field.  This is the
936147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * common case.  In performance critical code the JIT
937147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * will have tried this before calling out to the VM.
938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
939147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            newThin = thin | (threadId << LW_LOCK_OWNER_SHIFT);
940147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            if (!ATOMIC_CMP_SWAP((int32_t *)thinp, thin, newThin)) {
941147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                /*
942147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                 * The acquire failed.  Try again.
943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
944147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                goto retry;
945147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            }
946147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro        } else {
947147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            LOG_THIN("(%d) spin on lock %p: %#x (%#x) %#x",
948147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                     threadId, &obj->lock, 0, *thinp, thin);
949147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            /*
950147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * The lock is owned by another thread.  Notify the VM
951147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * that we are about to wait.
952147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             */
953147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            oldStatus = dvmChangeStatus(self, THREAD_MONITOR);
954147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            /*
955147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * Spin until the thin lock is released or inflated.
956147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             */
957147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            sleepDelay = 0;
958147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            for (;;) {
959147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                thin = *thinp;
960147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                /*
961147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                 * Check the shape of the lock word.  Another thread
962147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                 * may have inflated the lock while we were waiting.
963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
964147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
965147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                    if (LW_LOCK_OWNER(thin) == 0) {
966147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                        /*
967147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                         * The lock has been released.  Install the
968147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                         * thread id of the calling thread into the
969147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                         * owner field.
970147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                         */
971147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                        newThin = thin | (threadId << LW_LOCK_OWNER_SHIFT);
972147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                        if (ATOMIC_CMP_SWAP((int32_t *)thinp,
973147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                                            thin, newThin)) {
974147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                            /*
975147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                             * The acquire succeed.  Break out of the
976147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                             * loop and proceed to inflate the lock.
977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                             */
978147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                            break;
979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        }
980147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                    } else {
981147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                        /*
982147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                         * The lock has not been released.  Yield so
983147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                         * the owning thread can run.
984147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                         */
985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        if (sleepDelay == 0) {
986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            sched_yield();
987147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                            sleepDelay = 1000;
988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        } else {
989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            usleep(sleepDelay);
990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            if (sleepDelay < maxSleepDelay / 2) {
991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                sleepDelay *= 2;
992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            }
993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        }
994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
995147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                } else {
996147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                    /*
997147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                     * The thin lock was inflated by another thread.
998147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                     * Let the VM know we are no longer waiting and
999147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                     * try again.
1000147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                     */
1001147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                    LOG_THIN("(%d) lock %p surprise-fattened",
1002147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                             threadId, &obj->lock);
1003147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                    dvmChangeStatus(self, oldStatus);
1004147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                    goto retry;
1005147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                }
1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1007147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            LOG_THIN("(%d) spin on lock done %p: %#x (%#x) %#x",
1008147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                     threadId, &obj->lock, 0, *thinp, thin);
1009147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            /*
1010147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * We have acquired the thin lock.  Let the VM know that
1011147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * we are no longer waiting.
1012147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             */
1013147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            dvmChangeStatus(self, oldStatus);
1014147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            /*
1015147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro             * Fatten the lock.
1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
101766bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro            inflateMonitor(self, obj);
1018147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro            LOG_THIN("(%d) lock %p fattened", threadId, &obj->lock);
1019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1020147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    } else {
1021147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro        /*
1022147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro         * The lock is a fat lock.
1023147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro         */
1024147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro        assert(LW_MONITOR(obj->lock) != NULL);
1025147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro        lockMonitor(self, LW_MONITOR(obj->lock));
1026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
1028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * See if we were allowed to grab the lock at this time.  We do it
1030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * *after* acquiring the lock, rather than before, so that we can
1031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * freely update the Monitor struct.  This seems counter-intuitive,
1032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * but our goal is deadlock *prediction* not deadlock *prevention*.
1033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (If we actually deadlock, the situation is easy to diagnose from
1034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * a thread dump, so there's no point making a special effort to do
1035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the checks before the lock is held.)
1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * This needs to happen before we add the object to the thread's
1038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * monitor list, so we can tell the difference between first-lock and
1039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * re-lock.
1040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * It's also important that we do this while in THREAD_RUNNING, so
1042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that we don't interfere with cleanup operations in the GC.
1043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.deadlockPredictMode != kDPOff) {
1045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (self->status != THREAD_RUNNING) {
1046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Bad thread status (%d) in DP\n", self->status);
1047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmDumpThread(self, false);
1048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
1049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!dvmCheckException(self));
1051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        updateDeadlockPrediction(self, obj);
1052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmCheckException(self)) {
1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
1054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * If we're throwing an exception here, we need to free the
1055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * lock.  We add the object to the thread's monitor list so the
1056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * "unlock" code can remove it.
1057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAddToMonitorList(self, obj, false);
1059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmUnlockObject(self, obj);
1060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGV("--- unlocked, pending is '%s'\n",
1061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmGetException(self)->clazz->descriptor);
1062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Add the locked object, and the current stack trace, to the list
1067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * held by the Thread object.  If deadlock prediction isn't on,
1068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * don't capture the stack trace.
1069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmAddToMonitorList(self, obj, gDvm.deadlockPredictMode != kDPOff);
1071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#elif defined(WITH_MONITOR_TRACKING)
1072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Add the locked object to the list held by the Thread object.
1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmAddToMonitorList(self, obj, false);
1076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Implements monitorexit for "synchronized" stuff.
1081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * On failure, throws an exception and returns "false".
1083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmUnlockObject(Thread* self, Object *obj)
1085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
108694338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    u4 thin;
1087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1088ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro    assert(self != NULL);
1089ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro    assert(self->status == THREAD_RUNNING);
1090ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro    assert(obj != NULL);
1091ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro    /*
1092ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro     * Cache the lock word as its value can change while we are
1093ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro     * examining its state.
1094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1095147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro    thin = obj->lock;
1096ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro    if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
1097ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro        /*
1098ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro         * The lock is thin.  We must ensure that the lock is owned
1099ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro         * by the given thread before unlocking it.
1100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1101ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro        if (LW_LOCK_OWNER(thin) == self->threadId) {
1102ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro            /*
1103ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro             * We are the lock owner.  It is safe to update the lock
1104ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro             * without CAS as lock ownership guards the lock itself.
1105ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro             */
1106ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro            if (LW_LOCK_COUNT(thin) == 0) {
1107ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                /*
1108ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                 * The lock was not recursively acquired, the common
1109ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                 * case.  Unlock by clearing all bits except for the
1110ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                 * hash state.
1111ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                 */
1112147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                obj->lock &= (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT);
1113ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro            } else {
1114ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                /*
1115ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                 * The object was recursively acquired.  Decrement the
1116ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                 * lock recursion count field.
1117ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                 */
1118147dd3f9f0905dfc6687843a6ca3276031067505Carl Shapiro                obj->lock -= 1 << LW_LOCK_COUNT_SHIFT;
1119ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro            }
1120ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro        } else {
1121ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro            /*
1122ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro             * We do not own the lock.  The JVM spec requires that we
1123ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro             * throw an exception in this case.
1124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
1126ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro                              "unlock of unowned monitor");
1127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
1128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1130ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro        /*
1131ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro         * The lock is fat.  We must check to see if unlockMonitor has
1132ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro         * raised any exceptions before continuing.
1133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
11348d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        assert(LW_MONITOR(obj->lock) != NULL);
11358d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        if (!unlockMonitor(self, LW_MONITOR(obj->lock))) {
1136ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro            /*
1137ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro             * An exception has been raised.  Do not fall through.
1138ef5b4d3a0db17756c0e9bb90f14e18c4bf17a446Carl Shapiro             */
1139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
1140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_MONITOR_TRACKING
1144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Remove the object from the Thread's list.
1146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmRemoveFromMonitorList(self, obj);
1148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
1151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Object.wait().  Also called for class init.
1155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmObjectWait(Thread* self, Object *obj, s8 msec, s4 nsec,
1157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool interruptShouldThrow)
1158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
115966bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    Monitor* mon;
11608d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    u4 thin = obj->lock;
1161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* If the lock is still thin, we need to fatten it.
1163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
116494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
1165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Make sure that 'self' holds the lock.
1166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
116794338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        if (LW_LOCK_OWNER(thin) != self->threadId) {
1168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
1169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "object not locked by thread before wait()");
1170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
1171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* This thread holds the lock.  We need to fatten the lock
1174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * so 'self' can block on it.  Don't update the object lock
1175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * field yet, because 'self' needs to acquire the lock before
1176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * any other thread gets a chance.
1177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
117866bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro        inflateMonitor(self, obj);
117966bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro        LOG_THIN("(%d) lock %p fattened by wait() to count %d",
118066bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro                 self->threadId, &obj->lock, mon->lockCount);
1181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
118266bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro    mon = LW_MONITOR(obj->lock);
1183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    waitMonitor(self, mon, msec, nsec, interruptShouldThrow);
1184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Object.notify().
1188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmObjectNotify(Thread* self, Object *obj)
1190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
11918d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    u4 thin = obj->lock;
1192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* If the lock is still thin, there aren't any waiters;
1194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * waiting on an object forces lock fattening.
1195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
119694338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
1197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Make sure that 'self' holds the lock.
1198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
119994338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        if (LW_LOCK_OWNER(thin) != self->threadId) {
1200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
1201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "object not locked by thread before notify()");
1202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
1203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* no-op;  there are no waiters to notify.
1206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* It's a fat lock.
1209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
121094338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        notifyMonitor(self, LW_MONITOR(thin));
1211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Object.notifyAll().
1216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmObjectNotifyAll(Thread* self, Object *obj)
1218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
12198d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    u4 thin = obj->lock;
1220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* If the lock is still thin, there aren't any waiters;
1222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * waiting on an object forces lock fattening.
1223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
122494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
1225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Make sure that 'self' holds the lock.
1226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
122794338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        if (LW_LOCK_OWNER(thin) != self->threadId) {
1228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
1229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "object not locked by thread before notifyAll()");
1230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
1231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* no-op;  there are no waiters to notify.
1234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* It's a fat lock.
1237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
123894338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro        notifyAllMonitor(self, LW_MONITOR(thin));
1239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This implements java.lang.Thread.sleep(long msec, int nsec).
1244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The sleep is interruptible by other threads, which means we can't just
1246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * plop into an OS sleep call.  (We probably could if we wanted to send
1247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * signals around and rely on EINTR, but that's inefficient and relies
1248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * on native code respecting our signal mask.)
1249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We have to do all of this stuff for Object.wait() as well, so it's
1251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * easiest to just sleep on a private Monitor.
1252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It appears that we want sleep(0,0) to go through the motions of sleeping
1254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * for a very short duration, rather than just returning.
1255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmThreadSleep(u8 msec, u4 nsec)
1257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
1259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon = gDvm.threadSleepMon;
1260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* sleep(0,0) wakes up immediately, wait(0,0) means wait forever; adjust */
1262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (msec == 0 && nsec == 0)
1263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        nsec++;
1264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    lockMonitor(self, mon);
1266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    waitMonitor(self, mon, msec, nsec, true);
1267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unlockMonitor(self, mon);
1268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Implement java.lang.Thread.interrupt().
1272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
127377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapirovoid dvmThreadInterrupt(Thread* thread)
1274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
127577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    assert(thread != NULL);
127677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
1277980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro    dvmLockMutex(&thread->waitMutex);
127877f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
127977f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    /*
128077f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     * If the interrupted flag is already set no additional action is
128177f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     * required.
128277f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro     */
128377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (thread->interrupted == true) {
1284980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro        dvmUnlockMutex(&thread->waitMutex);
128577f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        return;
128677f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    }
128777f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro
1288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Raise the "interrupted" flag.  This will cause it to bail early out
1290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * of the next wait() attempt, if it's not currently waiting on
1291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * something.
1292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    thread->interrupted = true;
1294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MEM_BARRIER();
1295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Is the thread waiting?
1298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Note that fat vs. thin doesn't matter here;  waitMonitor
1300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * is only set when a thread actually waits on a monitor,
1301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * which implies that the monitor has already been fattened.
1302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
130377f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro    if (thread->waitMonitor != NULL) {
130477f52ebffa3793a7e824fab7da02eaee9afdae0eCarl Shapiro        pthread_cond_signal(&thread->waitCond);
1305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1307980ffb0243a1840ad0a93cfa06dfc02ca6f2d01cCarl Shapiro    dvmUnlockMutex(&thread->waitMutex);
1308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
131030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro#ifndef WITH_COPYING_GC
131194338aadf8355b28846f0d21c49142ca29479dc4Carl Shapirou4 dvmIdentityHashCode(Object *obj)
131294338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro{
131394338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro    return (u4)obj;
131494338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro}
131530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro#else
131630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro/*
131730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro * Returns the identity hash code of the given object.
131830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro */
131930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapirou4 dvmIdentityHashCode(Object *obj)
132030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro{
132130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    Thread *self, *thread;
132230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    volatile u4 *lw;
1323bfe4dcc3bd3d4d85a07fd3d63da537b51342b6ebCarl Shapiro    size_t size;
132430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    u4 lock, owner, hashState;
132530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro
132630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    if (obj == NULL) {
132730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
132830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * Null is defined to have an identity hash code of 0.
132930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
133030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        return 0;
133130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    }
133230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    lw = &obj->lock;
133330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiroretry:
133430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    hashState = LW_HASH_STATE(*lw);
133530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    if (hashState == LW_HASH_STATE_HASHED) {
133630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
133730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * The object has been hashed but has not had its hash code
133830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * relocated by the garbage collector.  Use the raw object
133930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * address.
134030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
134130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        return (u4)obj >> 3;
134230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    } else if (hashState == LW_HASH_STATE_HASHED_AND_MOVED) {
134330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
134430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * The object has been hashed and its hash code has been
134530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * relocated by the collector.  Use the value of the naturally
134630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * aligned word following the instance data.
134730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
1348c48b6d0dc6b8c01c65977a9d18203c8510687267Carl Shapiro        assert(obj->clazz != gDvm.classJavaLangClass);
1349c48b6d0dc6b8c01c65977a9d18203c8510687267Carl Shapiro        assert(obj->clazz != gDvm.unlinkedJavaLangClass);
135030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISARRAY)) {
1351bfe4dcc3bd3d4d85a07fd3d63da537b51342b6ebCarl Shapiro            size = dvmArrayObjectSize((ArrayObject *)obj);
1352c48b6d0dc6b8c01c65977a9d18203c8510687267Carl Shapiro            size = (size + 2) & ~2;
135330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        } else {
1354bfe4dcc3bd3d4d85a07fd3d63da537b51342b6ebCarl Shapiro            size = obj->clazz->objectSize;
135530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        }
1356bfe4dcc3bd3d4d85a07fd3d63da537b51342b6ebCarl Shapiro        return *(u4 *)(((char *)obj) + size);
135730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    } else if (hashState == LW_HASH_STATE_UNHASHED) {
135830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
135930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * The object has never been hashed.  Change the hash state to
136030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * hashed and use the raw object address.
136130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
136230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        self = dvmThreadSelf();
136330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        if (self->threadId == lockOwner(obj)) {
136430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            /*
136530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * We already own the lock so we can update the hash state
136630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * directly.
136730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             */
136830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            *lw |= (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT);
136930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            return (u4)obj >> 3;
137030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        }
137130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
137230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * We do not own the lock.  Try acquiring the lock.  Should
137330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * this fail, we must suspend the owning thread.
137430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
137530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        if (LW_SHAPE(*lw) == LW_SHAPE_THIN) {
137630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            /*
137730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * If the lock is thin assume it is unowned.  We simulate
137830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * an acquire, update, and release with a single CAS.
137930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             */
138030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            lock = DVM_LOCK_INITIAL_THIN_VALUE;
138130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            lock |= (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT);
138230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            if (ATOMIC_CMP_SWAP((int32_t *)lw,
138330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                                (int32_t)DVM_LOCK_INITIAL_THIN_VALUE,
138430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                                (int32_t)lock)) {
138530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                /*
138630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                 * A new lockword has been installed with a hash state
138730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                 * of hashed.  Use the raw object address.
138830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                 */
138930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                return (u4)obj >> 3;
139030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            }
139130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        } else {
139230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            if (tryLockMonitor(self, LW_MONITOR(*lw))) {
139330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                /*
139430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                 * The monitor lock has been acquired.  Change the
139530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                 * hash state to hashed and use the raw object
139630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                 * address.
139730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                 */
139830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                *lw |= (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT);
139930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                unlockMonitor(self, LW_MONITOR(*lw));
140030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                return (u4)obj >> 3;
140130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            }
140230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        }
140330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
140430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * At this point we have failed to acquire the lock.  We must
140530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * identify the owning thread and suspend it.
140630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
140730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        dvmLockThreadList(self);
140830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
140930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * Cache the lock word as its value can change between
141030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * determining its shape and retrieving its owner.
141130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
141230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        lock = *lw;
141330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        if (LW_SHAPE(lock) == LW_SHAPE_THIN) {
141430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            /*
141530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * Find the thread with the corresponding thread id.
141630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             */
141730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            owner = LW_LOCK_OWNER(lock);
141830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            assert(owner != self->threadId);
141930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            /*
142030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * If the lock has no owner do not bother scanning the
142130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * thread list and fall through to the failure handler.
142230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             */
142330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            thread = owner ? gDvm.threadList : NULL;
142430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            while (thread != NULL) {
142530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                if (thread->threadId == owner) {
142630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                    break;
142730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                }
142830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro                thread = thread->next;
142930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            }
143030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        } else {
143130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            thread = LW_MONITOR(lock)->owner;
143230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        }
143330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
143430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * If thread is NULL the object has been released since the
143530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * thread list lock was acquired.  Try again.
143630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
143730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        if (thread == NULL) {
143830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            dvmUnlockThreadList();
143930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            goto retry;
144030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        }
144130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
144230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * Wait for the owning thread to suspend.
144330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
144430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        dvmSuspendThread(thread);
144530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        if (dvmHoldsLock(thread, obj)) {
144630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            /*
144730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * The owning thread has been suspended.  We can safely
144830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             * change the hash state to hashed.
144930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro             */
145030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            *lw |= (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT);
145130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            dvmResumeThread(thread);
145230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            dvmUnlockThreadList();
145330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro            return (u4)obj >> 3;
145430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        }
145530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        /*
145630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         * The wrong thread has been suspended.  Try again.
145730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro         */
145830aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        dvmResumeThread(thread);
145930aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        dvmUnlockThreadList();
146030aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro        goto retry;
146130aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    }
146230aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    LOGE("object %p has an unknown hash state %#x", obj, hashState);
146330aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    dvmDumpThread(dvmThreadSelf(), false);
146430aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    dvmAbort();
146530aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro    return 0;  /* Quiet the compiler. */
146630aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro}
146730aa99778069baf0dab767f0fc1f5b1d51d110ffCarl Shapiro#endif  /* WITH_COPYING_GC */
1468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_DEADLOCK_PREDICTION
1470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
1472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Deadlock prediction
1473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
1474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe idea is to predict the possibility of deadlock by recording the order
1477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectin which monitors are acquired.  If we see an attempt to acquire a lock
1478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectout of order, we can identify the locks and offending code.
1479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectTo make this work, we need to keep track of the locks held by each thread,
1481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectand create history trees for each lock.  When a thread tries to acquire
1482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecta new lock, we walk through the "history children" of the lock, looking
1483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfor a match with locks the thread already holds.  If we find a match,
1484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectit means the thread has made a request that could result in a deadlock.
1485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectTo support recursive locks, we always allow re-locking a currently-held
1487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectlock, and maintain a recursion depth count.
1488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectAn ASCII-art example, where letters represent Objects:
1490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        A
1492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project       /|\
1493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project      / | \
1494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     B  |  D
1495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project      \ |
1496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project       \|
1497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        C
1498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe above is the tree we'd have after handling Object synchronization
1500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsequences "ABC", "AC", "AD".  A has three children, {B, C, D}.  C is also
1501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecta child of B.  (The lines represent pointers between parent and child.
1502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectEvery node can have multiple parents and multiple children.)
1503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectIf we hold AC, and want to lock B, we recursively search through B's
1505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchildren to see if A or C appears.  It does, so we reject the attempt.
1506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project(A straightforward way to implement it: add a link from C to B, then
1507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectdetermine whether the graph starting at B contains a cycle.)
1508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectIf we hold AC and want to lock D, we would succeed, creating a new link
1510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfrom C to D.
1511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe lock history and a stack trace is attached to the Object's Monitor
1513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstruct, which means we need to fatten every Object we lock (thin locking
1514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectis effectively disabled).  If we don't need the stack trace we can
1515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectavoid fattening the leaf nodes, only fattening objects that need to hold
1516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecthistory trees.
1517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectUpdates to Monitor structs are only allowed for the thread that holds
1519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe Monitor, so we actually do most of our deadlock prediction work after
1520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe lock has been acquired.
1521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectWhen an object with a monitor is GCed, we need to remove it from the
1523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecthistory trees.  There are two basic approaches:
1524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (1) For through the entire set of known monitors, search all child
1525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     lists for the object in question.  This is rather slow, resulting
1526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     in GC passes that take upwards of 10 seconds to complete.
1527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (2) Maintain "parent" pointers in each node.  Remove the entries as
1528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     required.  This requires additional storage and maintenance for
1529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     every operation, but is significantly faster at GC time.
1530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectFor each GCed object, we merge all of the object's children into each of
1531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe object's parents.
1532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project*/
1533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if !defined(WITH_MONITOR_TRACKING)
1535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# error "WITH_DEADLOCK_PREDICTION requires WITH_MONITOR_TRACKING"
1536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Clear out the contents of an ExpandingObjectList, freeing any
1540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * dynamic allocations.
1541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void expandObjClear(ExpandingObjectList* pList)
1543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pList->list != NULL) {
1545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(pList->list);
1546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pList->list = NULL;
1547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pList->alloc = pList->count = 0;
1549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the number of objects currently stored in the list.
1553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline int expandBufGetCount(const ExpandingObjectList* pList)
1555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return pList->count;
1557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the Nth entry from the list.
1561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline Object* expandBufGetEntry(const ExpandingObjectList* pList,
1563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i)
1564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return pList->list[i];
1566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add a new entry to the list.
1570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We don't check for or try to enforce uniqueness.  It's expected that
1572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the higher-level code does this for us.
1573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void expandObjAddEntry(ExpandingObjectList* pList, Object* obj)
1575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pList->count == pList->alloc) {
1577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* time to expand */
1578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object** newList;
1579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pList->alloc == 0)
1581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pList->alloc = 4;
1582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
1583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pList->alloc *= 2;
1584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("expanding %p to %d\n", pList, pList->alloc);
1585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newList = realloc(pList->list, pList->alloc * sizeof(Object*));
1586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (newList == NULL) {
1587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Failed expanding DP object list (alloc=%d)\n", pList->alloc);
1588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
1589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pList->list = newList;
1591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pList->list[pList->count++] = obj;
1594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if the element was successfully removed.
1598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool expandObjRemoveEntry(ExpandingObjectList* pList, Object* obj)
1600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = pList->count-1; i >= 0; i--) {
1604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pList->list[i] == obj)
1605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (i < 0)
1608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
1609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (i != pList->count-1) {
1611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The order of elements is not important, so we just copy the
1613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * last entry into the new slot.
1614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //memmove(&pList->list[i], &pList->list[i+1],
1616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    (pList->count-1 - i) * sizeof(pList->list[0]));
1617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pList->list[i] = pList->list[pList->count-1];
1618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pList->count--;
1621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pList->list[pList->count] = (Object*) 0xdecadead;
1622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
1623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if "obj" appears in the list.
1627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool expandObjHas(const ExpandingObjectList* pList, Object* obj)
1629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < pList->count; i++) {
1633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pList->list[i] == obj)
1634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
1635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return false;
1637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Print the list contents to stdout.  For debugging.
1641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void expandObjDump(const ExpandingObjectList* pList)
1643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < pList->count; i++)
1646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(" %p", pList->list[i]);
1647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Check for duplicate entries.  Returns the index of the first instance
1651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of the duplicated value, or -1 if no duplicates were found.
1652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int expandObjCheckForDuplicates(const ExpandingObjectList* pList)
1654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i, j;
1656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < pList->count-1; i++) {
1657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (j = i + 1; j < pList->count; j++) {
1658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (pList->list[i] == pList->list[j]) {
1659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return i;
1660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return -1;
1665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Determine whether "child" appears in the list of objects associated
1670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * with the Monitor in "parent".  If "parent" is a thin lock, we return
1671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * false immediately.
1672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool objectInChildList(const Object* parent, Object* child)
1674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
16758d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    u4 lock = parent->lock;
1676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!IS_LOCK_FAT(&lock)) {
1677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //LOGI("on thin\n");
1678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
1679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
16818d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    return expandObjHas(&LW_MONITOR(lock)->historyChildren, child);
1682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Print the child list.
1686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void dumpKids(Object* parent)
1688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
16898d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    Monitor* mon = LW_MONITOR(parent->lock);
1690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("Children of %p:", parent);
1692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    expandObjDump(&mon->historyChildren);
1693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("\n");
1694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add "child" to the list of children in "parent", and add "parent" to
1698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the list of parents in "child".
1699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void linkParentToChild(Object* parent, Object* child)
1701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
17028d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    //assert(LW_MONITOR(parent->lock)->owner == dvmThreadSelf());   // !owned for merge
1703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&parent->lock));
1704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&child->lock));
1705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(parent != child);
1706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon;
1707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17088d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    mon = LW_MONITOR(parent->lock);
1709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!expandObjHas(&mon->historyChildren, child));
1710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    expandObjAddEntry(&mon->historyChildren, child);
1711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17128d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    mon = LW_MONITOR(child->lock);
1713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!expandObjHas(&mon->historyParents, parent));
1714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    expandObjAddEntry(&mon->historyParents, parent);
1715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Remove "child" from the list of children in "parent".
1720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void unlinkParentFromChild(Object* parent, Object* child)
1722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
17238d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    //assert(LW_MONITOR(parent->lock)->owner == dvmThreadSelf());   // !owned for GC
1724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&parent->lock));
1725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&child->lock));
1726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(parent != child);
1727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon;
1728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17298d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    mon = LW_MONITOR(parent->lock);
1730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!expandObjRemoveEntry(&mon->historyChildren, child)) {
1731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("WARNING: child %p not found in parent %p\n", child, parent);
1732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!expandObjHas(&mon->historyChildren, child));
1734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(expandObjCheckForDuplicates(&mon->historyChildren) < 0);
1735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17368d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    mon = LW_MONITOR(child->lock);
1737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!expandObjRemoveEntry(&mon->historyParents, parent)) {
1738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("WARNING: parent %p not found in child %p\n", parent, child);
1739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!expandObjHas(&mon->historyParents, parent));
1741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(expandObjCheckForDuplicates(&mon->historyParents) < 0);
1742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Log the monitors held by the current thread.  This is done as part of
1747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * flagging an error.
1748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void logHeldMonitors(Thread* self)
1750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* name = NULL;
1752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    name = dvmGetThreadName(self);
1754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGW("Monitors currently held by thread (threadid=%d '%s')\n",
1755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        self->threadId, name);
1756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGW("(most-recently-acquired on top):\n");
1757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(name);
1758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LockedObjectData* lod = self->pLockedObjects;
1760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (lod != NULL) {
1761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("--- object %p[%d] (%s)\n",
1762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lod->obj, lod->recursionCount, lod->obj->clazz->descriptor);
1763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLogRawStackTrace(lod->rawStackTrace, lod->stackDepth);
1764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        lod = lod->next;
1766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Recursively traverse the object hierarchy starting at "obj".  We mark
1771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ourselves on entry and clear the mark on exit.  If we ever encounter
1772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a marked object, we have a cycle.
1773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if all is well, "false" if we found a cycle.
1775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool traverseTree(Thread* self, const Object* obj)
1777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&obj->lock));
17798d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    Monitor* mon = LW_MONITOR(obj->lock);
1780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Have we been here before?
1783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mon->historyMark) {
1785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int* rawStackTrace;
1786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int stackDepth;
1787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("%s\n", kStartBanner);
1789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("Illegal lock attempt:\n");
1790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("--- object %p (%s)\n", obj, obj->clazz->descriptor);
1791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        rawStackTrace = dvmFillInStackTraceRaw(self, &stackDepth);
1793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLogRawStackTrace(rawStackTrace, stackDepth);
1794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(rawStackTrace);
1795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW(" ");
1797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        logHeldMonitors(self);
1798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW(" ");
1800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("Earlier, the following lock order (from last to first) was\n");
1801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("established -- stack trace is from first successful lock):\n");
1802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
1803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->historyMark = true;
1805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Examine the children.  We do NOT hold these locks, so they might
1808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * very well transition from thin to fat or change ownership while
1809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we work.
1810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * NOTE: we rely on the fact that they cannot revert from fat to thin
1812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * while we work.  This is currently a safe assumption.
1813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We can safely ignore thin-locked children, because by definition
1815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * they have no history and are leaf nodes.  In the current
1816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * implementation we always fatten the locks to provide a place to
1817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * hang the stack trace.
1818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExpandingObjectList* pList = &mon->historyChildren;
1820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
1822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const Object* child = expandBufGetEntry(pList, i);
18238d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        u4 lock = child->lock;
1824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!IS_LOCK_FAT(&lock))
1825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            continue;
1826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!traverseTree(self, child)) {
1827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("--- object %p (%s)\n", obj, obj->clazz->descriptor);
1828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLogRawStackTrace(mon->historyRawStackTrace,
1829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                mon->historyStackDepth);
1830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mon->historyMark = false;
1831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
1832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon->historyMark = false;
1836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
1838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Update the deadlock prediction tree, based on the current thread
1842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * acquiring "acqObj".  This must be called before the object is added to
1843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the thread's list of held monitors.
1844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the thread already holds the lock (recursion), or this is a known
1846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * lock configuration, we return without doing anything.  Otherwise, we add
1847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a link from the most-recently-acquired lock in this thread to "acqObj"
1848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * after ensuring that the parent lock is "fat".
1849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This MUST NOT be called while a GC is in progress in another thread,
1851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because we assume exclusive access to history trees in owned monitors.
1852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void updateDeadlockPrediction(Thread* self, Object* acqObj)
1854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LockedObjectData* lod;
1856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LockedObjectData* mrl;
1857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Quick check for recursive access.
1860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    lod = dvmFindInMonitorList(self, acqObj);
1862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (lod != NULL) {
1863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("+++ DP: recursive %p\n", acqObj);
1864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Make the newly-acquired object's monitor "fat".  In some ways this
1869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * isn't strictly necessary, but we need the GC to tell us when
1870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * "interesting" objects go away, and right now the only way to make
1871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * an object look interesting is to give it a monitor.
1872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * This also gives us a place to hang a stack trace.
1874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Our thread holds the lock, so we're allowed to rewrite the lock
1876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * without worrying that something will change out from under us.
1877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!IS_LOCK_FAT(&acqObj->lock)) {
1879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("fattening lockee %p (recur=%d)\n",
188094338aadf8355b28846f0d21c49142ca29479dc4Carl Shapiro            acqObj, LW_LOCK_COUNT(acqObj->lock.thin));
188166bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro        inflateMonitor(self, acqObj);
1882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* if we don't have a stack trace for this monitor, establish one */
18858d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    if (LW_MONITOR(acqObj->lock)->historyRawStackTrace == NULL) {
18868d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        Monitor* mon = LW_MONITOR(acqObj->lock);
1887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon->historyRawStackTrace = dvmFillInStackTraceRaw(self,
1888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            &mon->historyStackDepth);
1889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We need to examine and perhaps modify the most-recently-locked
1893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * monitor.  We own that, so there's no risk of another thread
1894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * stepping on us.
1895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Retrieve the most-recently-locked entry from our thread.
1897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mrl = self->pLockedObjects;
1899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mrl == NULL)
1900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;         /* no other locks held */
1901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Do a quick check to see if "acqObj" is a direct descendant.  We can do
1904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * this without holding the global lock because of our assertion that
1905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * a GC is not running in parallel -- nobody except the GC can
1906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * modify a history list in a Monitor they don't own, and we own "mrl".
1907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (There might be concurrent *reads*, but no concurrent *writes.)
1908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If we find it, this is a known good configuration, and we're done.
1910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (objectInChildList(mrl->obj, acqObj))
1912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * "mrl" is going to need to have a history tree.  If it's currently
1916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * a thin lock, we make it fat now.  The thin lock might have a
1917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * nonzero recursive lock count, which we need to carry over.
1918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Our thread holds the lock, so we're allowed to rewrite the lock
1920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * without worrying that something will change out from under us.
1921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!IS_LOCK_FAT(&mrl->obj->lock)) {
1923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("fattening parent %p f/b/o child %p (recur=%d)\n",
19248d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro            mrl->obj, acqObj, LW_LOCK_COUNT(mrl->obj->lock));
192566bb7dfd93138c585d7be21863dd1b35e9607bd6Carl Shapiro        inflateMonitor(self, mrl->obj);
1926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We haven't seen this configuration before.  We need to scan down
1930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * acqObj's tree to see if any of the monitors in self->pLockedObjects
1931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * appear.  We grab a global lock before traversing or updating the
1932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * history list.
1933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If we find a match for any of our held locks, we know that the lock
1935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * has previously been acquired *after* acqObj, and we throw an error.
1936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The easiest way to do this is to create a link from "mrl" to "acqObj"
1938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * and do a recursive traversal, marking nodes as we cross them.  If
1939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we cross one a second time, we have a cycle and can throw an error.
1940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (We do the flag-clearing traversal before adding the new link, so
1941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that we're guaranteed to terminate.)
1942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If "acqObj" is a thin lock, it has no history, and we can create a
1944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * link to it without additional checks.  [ We now guarantee that it's
1945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * always fat. ]
1946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool failed = false;
1948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLockMutex(&gDvm.deadlockHistoryLock);
1949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    linkParentToChild(mrl->obj, acqObj);
1950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!traverseTree(self, acqObj)) {
1951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("%s\n", kEndBanner);
1952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        failed = true;
1953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* remove the entry so we're still okay when in "warning" mode */
1955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unlinkParentFromChild(mrl->obj, acqObj);
1956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmUnlockMutex(&gDvm.deadlockHistoryLock);
1958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (failed) {
1960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (gDvm.deadlockPredictMode) {
1961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kDPErr:
1962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ldalvik/system/PotentialDeadlockError;", NULL);
1963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kDPAbort:
1965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Aborting due to potential deadlock\n");
1966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
1967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        default:
1969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* warn only */
1970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're removing "child" from existence.  We want to pull all of
1977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * child's children into "parent", filtering out duplicates.  This is
1978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * called during the GC.
1979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This does not modify "child", which might have multiple parents.
1981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void mergeChildren(Object* parent, const Object* child)
1983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon;
1985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&child->lock));
19888d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    mon = LW_MONITOR(child->lock);
1989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExpandingObjectList* pList = &mon->historyChildren;
1990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
1992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* grandChild = expandBufGetEntry(pList, i);
1993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!objectInChildList(parent, grandChild)) {
1995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGVV("+++  migrating %p link to %p\n", grandChild, parent);
1996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            linkParentToChild(parent, grandChild);
1997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGVV("+++  parent %p already links to %p\n", parent, grandChild);
1999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * An object with a fat lock is being collected during a GC pass.  We
2005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * want to remove it from any lock history trees that it is a part of.
2006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This may require updating the history trees in several monitors.  The
2008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * monitor semantics guarantee that no other thread will be accessing
2009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the history trees at the same time.
2010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void removeCollectedObject(Object* obj)
2012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Monitor* mon;
2014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("+++ collecting %p\n", obj);
2016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
2018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We're currently running through the entire set of known monitors.
2020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * This can be somewhat slow.  We may want to keep lists of parents
2021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in each child to speed up GC.
2022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mon = gDvm.monitorList;
2024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (mon != NULL) {
2025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* parent = mon->obj;
2026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (parent != NULL) {       /* value nulled for deleted entries */
2027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (objectInChildList(parent, obj)) {
2028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGVV("removing child %p from parent %p\n", obj, parent);
2029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                unlinkParentFromChild(parent, obj);
2030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                mergeChildren(parent, obj);
2031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mon = mon->next;
2034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
2036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * For every parent of this object:
2039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  - merge all of our children into the parent's child list (creates
2040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *    a two-way link between parent and child)
2041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  - remove ourselves from the parent's child list
2042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExpandingObjectList* pList;
2044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
2045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(IS_LOCK_FAT(&obj->lock));
20478d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro    mon = LW_MONITOR(obj->lock);
2048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pList = &mon->historyParents;
2049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
2050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* parent = expandBufGetEntry(pList, i);
20518d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        Monitor* parentMon = LW_MONITOR(parent->lock);
2052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!expandObjRemoveEntry(&parentMon->historyChildren, obj)) {
2054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("WARNING: child %p not found in parent %p\n", obj, parent);
2055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!expandObjHas(&parentMon->historyChildren, obj));
2057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mergeChildren(parent, obj);
2059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * For every child of this object:
2063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  - remove ourselves from the child's parent list
2064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pList = &mon->historyChildren;
2066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
2067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* child = expandBufGetEntry(pList, i);
20688d7f9b2cd9fe252399ae96a36781bba1242fb93cCarl Shapiro        Monitor* childMon = LW_MONITOR(child->lock);
2069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!expandObjRemoveEntry(&childMon->historyParents, obj)) {
2071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("WARNING: parent %p not found in child %p\n", obj, child);
2072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!expandObjHas(&childMon->historyParents, obj));
2074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif /*WITH_DEADLOCK_PREDICTION*/
2078