107 DTRACE_MONITOR_PROBE(waited, monitor, obj(), thr); |
107 DTRACE_MONITOR_PROBE(waited, monitor, obj(), thr); |
108 return 0; |
108 return 0; |
109 } |
109 } |
110 |
110 |
111 #define NINFLATIONLOCKS 256 |
111 #define NINFLATIONLOCKS 256 |
112 static volatile intptr_t InflationLocks[NINFLATIONLOCKS]; |
112 static volatile intptr_t gInflationLocks[NINFLATIONLOCKS]; |
113 |
113 |
|
114 // global list of blocks of monitors |
114 // gBlockList is really PaddedEnd<ObjectMonitor> *, but we don't |
115 // gBlockList is really PaddedEnd<ObjectMonitor> *, but we don't |
115 // want to expose the PaddedEnd template more than necessary. |
116 // want to expose the PaddedEnd template more than necessary. |
116 ObjectMonitor * ObjectSynchronizer::gBlockList = NULL; |
117 ObjectMonitor * ObjectSynchronizer::gBlockList = NULL; |
|
118 // global monitor free list |
117 ObjectMonitor * volatile ObjectSynchronizer::gFreeList = NULL; |
119 ObjectMonitor * volatile ObjectSynchronizer::gFreeList = NULL; |
|
120 // global monitor in-use list, for moribund threads, |
|
121 // monitors they inflated need to be scanned for deflation |
118 ObjectMonitor * volatile ObjectSynchronizer::gOmInUseList = NULL; |
122 ObjectMonitor * volatile ObjectSynchronizer::gOmInUseList = NULL; |
|
123 // count of entries in gOmInUseList |
119 int ObjectSynchronizer::gOmInUseCount = 0; |
124 int ObjectSynchronizer::gOmInUseCount = 0; |
120 static volatile intptr_t ListLock = 0; // protects global monitor free-list cache |
125 |
121 static volatile int MonitorFreeCount = 0; // # on gFreeList |
126 static volatile intptr_t gListLock = 0; // protects global monitor lists |
122 static volatile int MonitorPopulation = 0; // # Extant -- in circulation |
127 static volatile int gMonitorFreeCount = 0; // # on gFreeList |
|
128 static volatile int gMonitorPopulation = 0; // # Extant -- in circulation |
|
129 |
123 #define CHAINMARKER (cast_to_oop<intptr_t>(-1)) |
130 #define CHAINMARKER (cast_to_oop<intptr_t>(-1)) |
124 |
131 |
125 |
132 |
126 // =====================> Quick functions |
133 // =====================> Quick functions |
127 |
134 |
526 // wakes at most one thread whereas we need to wake the entire list. |
533 // wakes at most one thread whereas we need to wake the entire list. |
527 int ix = (cast_from_oop<intptr_t>(obj) >> 5) & (NINFLATIONLOCKS-1); |
534 int ix = (cast_from_oop<intptr_t>(obj) >> 5) & (NINFLATIONLOCKS-1); |
528 int YieldThenBlock = 0; |
535 int YieldThenBlock = 0; |
529 assert(ix >= 0 && ix < NINFLATIONLOCKS, "invariant"); |
536 assert(ix >= 0 && ix < NINFLATIONLOCKS, "invariant"); |
530 assert((NINFLATIONLOCKS & (NINFLATIONLOCKS-1)) == 0, "invariant"); |
537 assert((NINFLATIONLOCKS & (NINFLATIONLOCKS-1)) == 0, "invariant"); |
531 Thread::muxAcquire(InflationLocks + ix, "InflationLock"); |
538 Thread::muxAcquire(gInflationLocks + ix, "gInflationLock"); |
532 while (obj->mark() == markOopDesc::INFLATING()) { |
539 while (obj->mark() == markOopDesc::INFLATING()) { |
533 // Beware: NakedYield() is advisory and has almost no effect on some platforms |
540 // Beware: NakedYield() is advisory and has almost no effect on some platforms |
534 // so we periodically call Self->_ParkEvent->park(1). |
541 // so we periodically call Self->_ParkEvent->park(1). |
535 // We use a mixed spin/yield/block mechanism. |
542 // We use a mixed spin/yield/block mechanism. |
536 if ((YieldThenBlock++) >= 16) { |
543 if ((YieldThenBlock++) >= 16) { |
537 Thread::current()->_ParkEvent->park(1); |
544 Thread::current()->_ParkEvent->park(1); |
538 } else { |
545 } else { |
539 os::naked_yield(); |
546 os::naked_yield(); |
540 } |
547 } |
541 } |
548 } |
542 Thread::muxRelease(InflationLocks + ix); |
549 Thread::muxRelease(gInflationLocks + ix); |
543 TEVENT(Inflate: INFLATING - yield/park); |
550 TEVENT(Inflate: INFLATING - yield/park); |
544 } |
551 } |
545 } else { |
552 } else { |
546 SpinPause(); // SMP-polite spinning |
553 SpinPause(); // SMP-polite spinning |
547 } |
554 } |
992 // to reprovision the caller's free list. |
999 // to reprovision the caller's free list. |
993 if (gFreeList != NULL) { |
1000 if (gFreeList != NULL) { |
994 // Reprovision the thread's omFreeList. |
1001 // Reprovision the thread's omFreeList. |
995 // Use bulk transfers to reduce the allocation rate and heat |
1002 // Use bulk transfers to reduce the allocation rate and heat |
996 // on various locks. |
1003 // on various locks. |
997 Thread::muxAcquire(&ListLock, "omAlloc"); |
1004 Thread::muxAcquire(&gListLock, "omAlloc"); |
998 for (int i = Self->omFreeProvision; --i >= 0 && gFreeList != NULL;) { |
1005 for (int i = Self->omFreeProvision; --i >= 0 && gFreeList != NULL;) { |
999 MonitorFreeCount--; |
1006 gMonitorFreeCount--; |
1000 ObjectMonitor * take = gFreeList; |
1007 ObjectMonitor * take = gFreeList; |
1001 gFreeList = take->FreeNext; |
1008 gFreeList = take->FreeNext; |
1002 guarantee(take->object() == NULL, "invariant"); |
1009 guarantee(take->object() == NULL, "invariant"); |
1003 guarantee(!take->is_busy(), "invariant"); |
1010 guarantee(!take->is_busy(), "invariant"); |
1004 take->Recycle(); |
1011 take->Recycle(); |
1005 omRelease(Self, take, false); |
1012 omRelease(Self, take, false); |
1006 } |
1013 } |
1007 Thread::muxRelease(&ListLock); |
1014 Thread::muxRelease(&gListLock); |
1008 Self->omFreeProvision += 1 + (Self->omFreeProvision/2); |
1015 Self->omFreeProvision += 1 + (Self->omFreeProvision/2); |
1009 if (Self->omFreeProvision > MAXPRIVATE) Self->omFreeProvision = MAXPRIVATE; |
1016 if (Self->omFreeProvision > MAXPRIVATE) Self->omFreeProvision = MAXPRIVATE; |
1010 TEVENT(omFirst - reprovision); |
1017 TEVENT(omFirst - reprovision); |
1011 |
1018 |
1012 const int mx = MonitorBound; |
1019 const int mx = MonitorBound; |
1013 if (mx > 0 && (MonitorPopulation-MonitorFreeCount) > mx) { |
1020 if (mx > 0 && (gMonitorPopulation-gMonitorFreeCount) > mx) { |
1014 // We can't safely induce a STW safepoint from omAlloc() as our thread |
1021 // We can't safely induce a STW safepoint from omAlloc() as our thread |
1015 // state may not be appropriate for such activities and callers may hold |
1022 // state may not be appropriate for such activities and callers may hold |
1016 // naked oops, so instead we defer the action. |
1023 // naked oops, so instead we defer the action. |
1017 InduceScavenge(Self, "omAlloc"); |
1024 InduceScavenge(Self, "omAlloc"); |
1018 } |
1025 } |
1066 |
1073 |
1067 // Consider carving out this thread's current request from the |
1074 // Consider carving out this thread's current request from the |
1068 // block in hand. This avoids some lock traffic and redundant |
1075 // block in hand. This avoids some lock traffic and redundant |
1069 // list activity. |
1076 // list activity. |
1070 |
1077 |
1071 // Acquire the ListLock to manipulate BlockList and FreeList. |
1078 // Acquire the gListLock to manipulate gBlockList and gFreeList. |
1072 // An Oyama-Taura-Yonezawa scheme might be more efficient. |
1079 // An Oyama-Taura-Yonezawa scheme might be more efficient. |
1073 Thread::muxAcquire(&ListLock, "omAlloc [2]"); |
1080 Thread::muxAcquire(&gListLock, "omAlloc [2]"); |
1074 MonitorPopulation += _BLOCKSIZE-1; |
1081 gMonitorPopulation += _BLOCKSIZE-1; |
1075 MonitorFreeCount += _BLOCKSIZE-1; |
1082 gMonitorFreeCount += _BLOCKSIZE-1; |
1076 |
1083 |
1077 // Add the new block to the list of extant blocks (gBlockList). |
1084 // Add the new block to the list of extant blocks (gBlockList). |
1078 // The very first objectMonitor in a block is reserved and dedicated. |
1085 // The very first objectMonitor in a block is reserved and dedicated. |
1079 // It serves as blocklist "next" linkage. |
1086 // It serves as blocklist "next" linkage. |
1080 temp[0].FreeNext = gBlockList; |
1087 temp[0].FreeNext = gBlockList; |
1081 gBlockList = temp; |
1088 gBlockList = temp; |
1082 |
1089 |
1083 // Add the new string of objectMonitors to the global free list |
1090 // Add the new string of objectMonitors to the global free list |
1084 temp[_BLOCKSIZE - 1].FreeNext = gFreeList; |
1091 temp[_BLOCKSIZE - 1].FreeNext = gFreeList; |
1085 gFreeList = temp + 1; |
1092 gFreeList = temp + 1; |
1086 Thread::muxRelease(&ListLock); |
1093 Thread::muxRelease(&gListLock); |
1087 TEVENT(Allocate block of monitors); |
1094 TEVENT(Allocate block of monitors); |
1088 } |
1095 } |
1089 } |
1096 } |
1090 |
1097 |
1091 // Place "m" on the caller's private per-thread omFreeList. |
1098 // Place "m" on the caller's private per-thread omFreeList. |
1092 // In practice there's no need to clamp or limit the number of |
1099 // In practice there's no need to clamp or limit the number of |
1093 // monitors on a thread's omFreeList as the only time we'll call |
1100 // monitors on a thread's omFreeList as the only time we'll call |
1094 // omRelease is to return a monitor to the free list after a CAS |
1101 // omRelease is to return a monitor to the free list after a CAS |
1095 // attempt failed. This doesn't allow unbounded #s of monitors to |
1102 // attempt failed. This doesn't allow unbounded #s of monitors to |
1096 // accumulate on a thread's free list. |
1103 // accumulate on a thread's free list. |
|
1104 // |
|
1105 // Key constraint: all ObjectMonitors on a thread's free list and the global |
|
1106 // free list must have their object field set to null. This prevents the |
|
1107 // scavenger -- deflate_idle_monitors -- from reclaiming them. |
1097 |
1108 |
1098 void ObjectSynchronizer::omRelease(Thread * Self, ObjectMonitor * m, |
1109 void ObjectSynchronizer::omRelease(Thread * Self, ObjectMonitor * m, |
1099 bool fromPerThreadAlloc) { |
1110 bool fromPerThreadAlloc) { |
1100 guarantee(m->object() == NULL, "invariant"); |
1111 guarantee(m->object() == NULL, "invariant"); |
1101 |
1112 guarantee(((m->is_busy()|m->_recursions) == 0), "freeing in-use monitor"); |
1102 // Remove from omInUseList |
1113 // Remove from omInUseList |
1103 if (MonitorInUseLists && fromPerThreadAlloc) { |
1114 if (MonitorInUseLists && fromPerThreadAlloc) { |
1104 ObjectMonitor* curmidinuse = NULL; |
1115 ObjectMonitor* cur_mid_in_use = NULL; |
1105 for (ObjectMonitor* mid = Self->omInUseList; mid != NULL;) { |
1116 bool extracted = false; |
|
1117 for (ObjectMonitor* mid = Self->omInUseList; mid != NULL; cur_mid_in_use = mid, mid = mid->FreeNext) { |
1106 if (m == mid) { |
1118 if (m == mid) { |
1107 // extract from per-thread in-use-list |
1119 // extract from per-thread in-use list |
1108 if (mid == Self->omInUseList) { |
1120 if (mid == Self->omInUseList) { |
1109 Self->omInUseList = mid->FreeNext; |
1121 Self->omInUseList = mid->FreeNext; |
1110 } else if (curmidinuse != NULL) { |
1122 } else if (cur_mid_in_use != NULL) { |
1111 curmidinuse->FreeNext = mid->FreeNext; // maintain the current thread inuselist |
1123 cur_mid_in_use->FreeNext = mid->FreeNext; // maintain the current thread in-use list |
1112 } |
1124 } |
|
1125 extracted = true; |
1113 Self->omInUseCount--; |
1126 Self->omInUseCount--; |
1114 if (ObjectMonitor::Knob_VerifyInUse) { |
1127 if (ObjectMonitor::Knob_VerifyInUse) { |
1115 verifyInUse(Self); |
1128 verifyInUse(Self); |
1116 } |
1129 } |
1117 break; |
1130 break; |
1118 } else { |
|
1119 curmidinuse = mid; |
|
1120 mid = mid->FreeNext; |
|
1121 } |
1131 } |
1122 } |
1132 } |
|
1133 assert(extracted, "Should have extracted from in-use list"); |
1123 } |
1134 } |
1124 |
1135 |
1125 // FreeNext is used for both omInUseList and omFreeList, so clear old before setting new |
1136 // FreeNext is used for both omInUseList and omFreeList, so clear old before setting new |
1126 m->FreeNext = Self->omFreeList; |
1137 m->FreeNext = Self->omFreeList; |
1127 Self->omFreeList = m; |
1138 Self->omFreeList = m; |
1147 // not at a safepoint at the time of the call, and thus there could |
1158 // not at a safepoint at the time of the call, and thus there could |
1148 // be not inopportune interleavings between omFlush() and the scavenge |
1159 // be not inopportune interleavings between omFlush() and the scavenge |
1149 // operator. |
1160 // operator. |
1150 |
1161 |
1151 void ObjectSynchronizer::omFlush(Thread * Self) { |
1162 void ObjectSynchronizer::omFlush(Thread * Self) { |
1152 ObjectMonitor * List = Self->omFreeList; // Null-terminated SLL |
1163 ObjectMonitor * list = Self->omFreeList; // Null-terminated SLL |
1153 Self->omFreeList = NULL; |
1164 Self->omFreeList = NULL; |
1154 ObjectMonitor * Tail = NULL; |
1165 ObjectMonitor * tail = NULL; |
1155 int Tally = 0; |
1166 int tally = 0; |
1156 if (List != NULL) { |
1167 if (list != NULL) { |
1157 ObjectMonitor * s; |
1168 ObjectMonitor * s; |
1158 for (s = List; s != NULL; s = s->FreeNext) { |
1169 // The thread is going away, the per-thread free monitors |
1159 Tally++; |
1170 // are freed via set_owner(NULL) |
1160 Tail = s; |
1171 // Link them to tail, which will be linked into the global free list |
|
1172 // gFreeList below, under the gListLock |
|
1173 for (s = list; s != NULL; s = s->FreeNext) { |
|
1174 tally++; |
|
1175 tail = s; |
1161 guarantee(s->object() == NULL, "invariant"); |
1176 guarantee(s->object() == NULL, "invariant"); |
1162 guarantee(!s->is_busy(), "invariant"); |
1177 guarantee(!s->is_busy(), "invariant"); |
1163 s->set_owner(NULL); // redundant but good hygiene |
1178 s->set_owner(NULL); // redundant but good hygiene |
1164 TEVENT(omFlush - Move one); |
1179 TEVENT(omFlush - Move one); |
1165 } |
1180 } |
1166 guarantee(Tail != NULL && List != NULL, "invariant"); |
1181 guarantee(tail != NULL && list != NULL, "invariant"); |
1167 } |
1182 } |
1168 |
1183 |
1169 ObjectMonitor * InUseList = Self->omInUseList; |
1184 ObjectMonitor * inUseList = Self->omInUseList; |
1170 ObjectMonitor * InUseTail = NULL; |
1185 ObjectMonitor * inUseTail = NULL; |
1171 int InUseTally = 0; |
1186 int inUseTally = 0; |
1172 if (InUseList != NULL) { |
1187 if (inUseList != NULL) { |
1173 Self->omInUseList = NULL; |
1188 Self->omInUseList = NULL; |
1174 ObjectMonitor *curom; |
1189 ObjectMonitor *cur_om; |
1175 for (curom = InUseList; curom != NULL; curom = curom->FreeNext) { |
1190 // The thread is going away, however the omInUseList inflated |
1176 InUseTail = curom; |
1191 // monitors may still be in-use by other threads. |
1177 InUseTally++; |
1192 // Link them to inUseTail, which will be linked into the global in-use list |
1178 } |
1193 // gOmInUseList below, under the gListLock |
1179 assert(Self->omInUseCount == InUseTally, "inuse count off"); |
1194 for (cur_om = inUseList; cur_om != NULL; cur_om = cur_om->FreeNext) { |
|
1195 inUseTail = cur_om; |
|
1196 inUseTally++; |
|
1197 } |
|
1198 assert(Self->omInUseCount == inUseTally, "in-use count off"); |
1180 Self->omInUseCount = 0; |
1199 Self->omInUseCount = 0; |
1181 guarantee(InUseTail != NULL && InUseList != NULL, "invariant"); |
1200 guarantee(inUseTail != NULL && inUseList != NULL, "invariant"); |
1182 } |
1201 } |
1183 |
1202 |
1184 Thread::muxAcquire(&ListLock, "omFlush"); |
1203 Thread::muxAcquire(&gListLock, "omFlush"); |
1185 if (Tail != NULL) { |
1204 if (tail != NULL) { |
1186 Tail->FreeNext = gFreeList; |
1205 tail->FreeNext = gFreeList; |
1187 gFreeList = List; |
1206 gFreeList = list; |
1188 MonitorFreeCount += Tally; |
1207 gMonitorFreeCount += tally; |
1189 } |
1208 } |
1190 |
1209 |
1191 if (InUseTail != NULL) { |
1210 if (inUseTail != NULL) { |
1192 InUseTail->FreeNext = gOmInUseList; |
1211 inUseTail->FreeNext = gOmInUseList; |
1193 gOmInUseList = InUseList; |
1212 gOmInUseList = inUseList; |
1194 gOmInUseCount += InUseTally; |
1213 gOmInUseCount += inUseTally; |
1195 } |
1214 } |
1196 |
1215 |
1197 Thread::muxRelease(&ListLock); |
1216 Thread::muxRelease(&gListLock); |
1198 TEVENT(omFlush); |
1217 TEVENT(omFlush); |
1199 } |
1218 } |
1200 |
1219 |
1201 // Fast path code shared by multiple functions |
1220 // Fast path code shared by multiple functions |
1202 ObjectMonitor* ObjectSynchronizer::inflate_helper(oop obj) { |
1221 ObjectMonitor* ObjectSynchronizer::inflate_helper(oop obj) { |
1409 // impacts the performance of some applications (e.g., PointBase). |
1428 // impacts the performance of some applications (e.g., PointBase). |
1410 // Broadly, we want to minimize the # of monitors in circulation. |
1429 // Broadly, we want to minimize the # of monitors in circulation. |
1411 // |
1430 // |
1412 // We have added a flag, MonitorInUseLists, which creates a list |
1431 // We have added a flag, MonitorInUseLists, which creates a list |
1413 // of active monitors for each thread. deflate_idle_monitors() |
1432 // of active monitors for each thread. deflate_idle_monitors() |
1414 // only scans the per-thread inuse lists. omAlloc() puts all |
1433 // only scans the per-thread in-use lists. omAlloc() puts all |
1415 // assigned monitors on the per-thread list. deflate_idle_monitors() |
1434 // assigned monitors on the per-thread list. deflate_idle_monitors() |
1416 // returns the non-busy monitors to the global free list. |
1435 // returns the non-busy monitors to the global free list. |
1417 // When a thread dies, omFlush() adds the list of active monitors for |
1436 // When a thread dies, omFlush() adds the list of active monitors for |
1418 // that thread to a global gOmInUseList acquiring the |
1437 // that thread to a global gOmInUseList acquiring the |
1419 // global list lock. deflate_idle_monitors() acquires the global |
1438 // global list lock. deflate_idle_monitors() acquires the global |
1420 // list lock to scan for non-busy monitors to the global free list. |
1439 // list lock to scan for non-busy monitors to the global free list. |
1421 // An alternative could have used a single global inuse list. The |
1440 // An alternative could have used a single global in-use list. The |
1422 // downside would have been the additional cost of acquiring the global list lock |
1441 // downside would have been the additional cost of acquiring the global list lock |
1423 // for every omAlloc(). |
1442 // for every omAlloc(). |
1424 // |
1443 // |
1425 // Perversely, the heap size -- and thus the STW safepoint rate -- |
1444 // Perversely, the heap size -- and thus the STW safepoint rate -- |
1426 // typically drives the scavenge rate. Large heaps can mean infrequent GC, |
1445 // typically drives the scavenge rate. Large heaps can mean infrequent GC, |
1463 obj->release_set_mark(mid->header()); |
1482 obj->release_set_mark(mid->header()); |
1464 mid->clear(); |
1483 mid->clear(); |
1465 |
1484 |
1466 assert(mid->object() == NULL, "invariant"); |
1485 assert(mid->object() == NULL, "invariant"); |
1467 |
1486 |
1468 // Move the object to the working free list defined by FreeHead,FreeTail. |
1487 // Move the object to the working free list defined by freeHeadp, freeTailp |
1469 if (*freeHeadp == NULL) *freeHeadp = mid; |
1488 if (*freeHeadp == NULL) *freeHeadp = mid; |
1470 if (*freeTailp != NULL) { |
1489 if (*freeTailp != NULL) { |
1471 ObjectMonitor * prevtail = *freeTailp; |
1490 ObjectMonitor * prevtail = *freeTailp; |
1472 assert(prevtail->FreeNext == NULL, "cleaned up deflated?"); // TODO KK |
1491 assert(prevtail->FreeNext == NULL, "cleaned up deflated?"); |
1473 prevtail->FreeNext = mid; |
1492 prevtail->FreeNext = mid; |
1474 } |
1493 } |
1475 *freeTailp = mid; |
1494 *freeTailp = mid; |
1476 deflated = true; |
1495 deflated = true; |
1477 } |
1496 } |
1478 return deflated; |
1497 return deflated; |
1479 } |
1498 } |
1480 |
1499 |
1481 // Caller acquires ListLock |
1500 // Walk a given monitor list, and deflate idle monitors |
1482 int ObjectSynchronizer::walk_monitor_list(ObjectMonitor** listheadp, |
1501 // The given list could be a per-thread list or a global list |
1483 ObjectMonitor** freeHeadp, |
1502 // Caller acquires gListLock |
1484 ObjectMonitor** freeTailp) { |
1503 int ObjectSynchronizer::deflate_monitor_list(ObjectMonitor** listHeadp, |
|
1504 ObjectMonitor** freeHeadp, |
|
1505 ObjectMonitor** freeTailp) { |
1485 ObjectMonitor* mid; |
1506 ObjectMonitor* mid; |
1486 ObjectMonitor* next; |
1507 ObjectMonitor* next; |
1487 ObjectMonitor* curmidinuse = NULL; |
1508 ObjectMonitor* cur_mid_in_use = NULL; |
1488 int deflatedcount = 0; |
1509 int deflated_count = 0; |
1489 |
1510 |
1490 for (mid = *listheadp; mid != NULL;) { |
1511 for (mid = *listHeadp; mid != NULL;) { |
1491 oop obj = (oop) mid->object(); |
1512 oop obj = (oop) mid->object(); |
1492 bool deflated = false; |
1513 if (obj != NULL && deflate_monitor(mid, obj, freeHeadp, freeTailp)) { |
1493 if (obj != NULL) { |
1514 // if deflate_monitor succeeded, |
1494 deflated = deflate_monitor(mid, obj, freeHeadp, freeTailp); |
1515 // extract from per-thread in-use list |
1495 } |
1516 if (mid == *listHeadp) { |
1496 if (deflated) { |
1517 *listHeadp = mid->FreeNext; |
1497 // extract from per-thread in-use-list |
1518 } else if (cur_mid_in_use != NULL) { |
1498 if (mid == *listheadp) { |
1519 cur_mid_in_use->FreeNext = mid->FreeNext; // maintain the current thread in-use list |
1499 *listheadp = mid->FreeNext; |
|
1500 } else if (curmidinuse != NULL) { |
|
1501 curmidinuse->FreeNext = mid->FreeNext; // maintain the current thread inuselist |
|
1502 } |
1520 } |
1503 next = mid->FreeNext; |
1521 next = mid->FreeNext; |
1504 mid->FreeNext = NULL; // This mid is current tail in the FreeHead list |
1522 mid->FreeNext = NULL; // This mid is current tail in the freeHeadp list |
1505 mid = next; |
1523 mid = next; |
1506 deflatedcount++; |
1524 deflated_count++; |
1507 } else { |
1525 } else { |
1508 curmidinuse = mid; |
1526 cur_mid_in_use = mid; |
1509 mid = mid->FreeNext; |
1527 mid = mid->FreeNext; |
1510 } |
1528 } |
1511 } |
1529 } |
1512 return deflatedcount; |
1530 return deflated_count; |
1513 } |
1531 } |
1514 |
1532 |
1515 void ObjectSynchronizer::deflate_idle_monitors() { |
1533 void ObjectSynchronizer::deflate_idle_monitors() { |
1516 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); |
1534 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); |
1517 int nInuse = 0; // currently associated with objects |
1535 int nInuse = 0; // currently associated with objects |
1518 int nInCirculation = 0; // extant |
1536 int nInCirculation = 0; // extant |
1519 int nScavenged = 0; // reclaimed |
1537 int nScavenged = 0; // reclaimed |
1520 bool deflated = false; |
1538 bool deflated = false; |
1521 |
1539 |
1522 ObjectMonitor * FreeHead = NULL; // Local SLL of scavenged monitors |
1540 ObjectMonitor * freeHeadp = NULL; // Local SLL of scavenged monitors |
1523 ObjectMonitor * FreeTail = NULL; |
1541 ObjectMonitor * freeTailp = NULL; |
1524 |
1542 |
1525 TEVENT(deflate_idle_monitors); |
1543 TEVENT(deflate_idle_monitors); |
1526 // Prevent omFlush from changing mids in Thread dtor's during deflation |
1544 // Prevent omFlush from changing mids in Thread dtor's during deflation |
1527 // And in case the vm thread is acquiring a lock during a safepoint |
1545 // And in case the vm thread is acquiring a lock during a safepoint |
1528 // See e.g. 6320749 |
1546 // See e.g. 6320749 |
1529 Thread::muxAcquire(&ListLock, "scavenge - return"); |
1547 Thread::muxAcquire(&gListLock, "scavenge - return"); |
1530 |
1548 |
1531 if (MonitorInUseLists) { |
1549 if (MonitorInUseLists) { |
1532 int inUse = 0; |
1550 int inUse = 0; |
1533 for (JavaThread* cur = Threads::first(); cur != NULL; cur = cur->next()) { |
1551 for (JavaThread* cur = Threads::first(); cur != NULL; cur = cur->next()) { |
1534 nInCirculation+= cur->omInUseCount; |
1552 nInCirculation+= cur->omInUseCount; |
1535 int deflatedcount = walk_monitor_list(cur->omInUseList_addr(), &FreeHead, &FreeTail); |
1553 int deflated_count = deflate_monitor_list(cur->omInUseList_addr(), &freeHeadp, &freeTailp); |
1536 cur->omInUseCount-= deflatedcount; |
1554 cur->omInUseCount-= deflated_count; |
1537 if (ObjectMonitor::Knob_VerifyInUse) { |
1555 if (ObjectMonitor::Knob_VerifyInUse) { |
1538 verifyInUse(cur); |
1556 verifyInUse(cur); |
1539 } |
1557 } |
1540 nScavenged += deflatedcount; |
1558 nScavenged += deflated_count; |
1541 nInuse += cur->omInUseCount; |
1559 nInuse += cur->omInUseCount; |
1542 } |
1560 } |
1543 |
1561 |
1544 // For moribund threads, scan gOmInUseList |
1562 // For moribund threads, scan gOmInUseList |
1545 if (gOmInUseList) { |
1563 if (gOmInUseList) { |
1546 nInCirculation += gOmInUseCount; |
1564 nInCirculation += gOmInUseCount; |
1547 int deflatedcount = walk_monitor_list((ObjectMonitor **)&gOmInUseList, &FreeHead, &FreeTail); |
1565 int deflated_count = deflate_monitor_list((ObjectMonitor **)&gOmInUseList, &freeHeadp, &freeTailp); |
1548 gOmInUseCount-= deflatedcount; |
1566 gOmInUseCount-= deflated_count; |
1549 nScavenged += deflatedcount; |
1567 nScavenged += deflated_count; |
1550 nInuse += gOmInUseCount; |
1568 nInuse += gOmInUseCount; |
1551 } |
1569 } |
1552 |
1570 |
1553 } else for (PaddedEnd<ObjectMonitor> * block = |
1571 } else for (PaddedEnd<ObjectMonitor> * block = |
1554 (PaddedEnd<ObjectMonitor> *)gBlockList; block != NULL; |
1572 (PaddedEnd<ObjectMonitor> *)gBlockList; block != NULL; |
1566 // free list or the global free list. |
1584 // free list or the global free list. |
1567 // obj == NULL IMPLIES mid->is_busy() == 0 |
1585 // obj == NULL IMPLIES mid->is_busy() == 0 |
1568 guarantee(!mid->is_busy(), "invariant"); |
1586 guarantee(!mid->is_busy(), "invariant"); |
1569 continue; |
1587 continue; |
1570 } |
1588 } |
1571 deflated = deflate_monitor(mid, obj, &FreeHead, &FreeTail); |
1589 deflated = deflate_monitor(mid, obj, &freeHeadp, &freeTailp); |
1572 |
1590 |
1573 if (deflated) { |
1591 if (deflated) { |
1574 mid->FreeNext = NULL; |
1592 mid->FreeNext = NULL; |
1575 nScavenged++; |
1593 nScavenged++; |
1576 } else { |
1594 } else { |
1577 nInuse++; |
1595 nInuse++; |
1578 } |
1596 } |
1579 } |
1597 } |
1580 } |
1598 } |
1581 |
1599 |
1582 MonitorFreeCount += nScavenged; |
1600 gMonitorFreeCount += nScavenged; |
1583 |
1601 |
1584 // Consider: audit gFreeList to ensure that MonitorFreeCount and list agree. |
1602 // Consider: audit gFreeList to ensure that gMonitorFreeCount and list agree. |
1585 |
1603 |
1586 if (ObjectMonitor::Knob_Verbose) { |
1604 if (ObjectMonitor::Knob_Verbose) { |
1587 ::printf("Deflate: InCirc=%d InUse=%d Scavenged=%d ForceMonitorScavenge=%d : pop=%d free=%d\n", |
1605 ::printf("Deflate: InCirc=%d InUse=%d Scavenged=%d ForceMonitorScavenge=%d : pop=%d free=%d\n", |
1588 nInCirculation, nInuse, nScavenged, ForceMonitorScavenge, |
1606 nInCirculation, nInuse, nScavenged, ForceMonitorScavenge, |
1589 MonitorPopulation, MonitorFreeCount); |
1607 gMonitorPopulation, gMonitorFreeCount); |
1590 ::fflush(stdout); |
1608 ::fflush(stdout); |
1591 } |
1609 } |
1592 |
1610 |
1593 ForceMonitorScavenge = 0; // Reset |
1611 ForceMonitorScavenge = 0; // Reset |
1594 |
1612 |
1595 // Move the scavenged monitors back to the global free list. |
1613 // Move the scavenged monitors back to the global free list. |
1596 if (FreeHead != NULL) { |
1614 if (freeHeadp != NULL) { |
1597 guarantee(FreeTail != NULL && nScavenged > 0, "invariant"); |
1615 guarantee(freeTailp != NULL && nScavenged > 0, "invariant"); |
1598 assert(FreeTail->FreeNext == NULL, "invariant"); |
1616 assert(freeTailp->FreeNext == NULL, "invariant"); |
1599 // constant-time list splice - prepend scavenged segment to gFreeList |
1617 // constant-time list splice - prepend scavenged segment to gFreeList |
1600 FreeTail->FreeNext = gFreeList; |
1618 freeTailp->FreeNext = gFreeList; |
1601 gFreeList = FreeHead; |
1619 gFreeList = freeHeadp; |
1602 } |
1620 } |
1603 Thread::muxRelease(&ListLock); |
1621 Thread::muxRelease(&gListLock); |
1604 |
1622 |
1605 if (ObjectMonitor::_sync_Deflations != NULL) ObjectMonitor::_sync_Deflations->inc(nScavenged); |
1623 if (ObjectMonitor::_sync_Deflations != NULL) ObjectMonitor::_sync_Deflations->inc(nScavenged); |
1606 if (ObjectMonitor::_sync_MonExtant != NULL) ObjectMonitor::_sync_MonExtant ->set_value(nInCirculation); |
1624 if (ObjectMonitor::_sync_MonExtant != NULL) ObjectMonitor::_sync_MonExtant ->set_value(nInCirculation); |
1607 |
1625 |
1608 // TODO: Add objectMonitor leak detection. |
1626 // TODO: Add objectMonitor leak detection. |