src/hotspot/share/runtime/synchronizer.cpp
changeset 55345 492b644bb9c2
parent 54786 ebf733a324d4
child 57602 dbe471d2f8f8
equal deleted inserted replaced
55344:0c20dbc3d547 55345:492b644bb9c2
   240     // and last are the inflated Java Monitor (ObjectMonitor) checks.
   240     // and last are the inflated Java Monitor (ObjectMonitor) checks.
   241     lock->set_displaced_header(markOopDesc::unused_mark());
   241     lock->set_displaced_header(markOopDesc::unused_mark());
   242 
   242 
   243     if (owner == NULL && Atomic::replace_if_null(Self, &(m->_owner))) {
   243     if (owner == NULL && Atomic::replace_if_null(Self, &(m->_owner))) {
   244       assert(m->_recursions == 0, "invariant");
   244       assert(m->_recursions == 0, "invariant");
   245       assert(m->_owner == Self, "invariant");
       
   246       return true;
   245       return true;
   247     }
   246     }
   248   }
   247   }
   249 
   248 
   250   // Note that we could inflate in quick_enter.
   249   // Note that we could inflate in quick_enter.
  1028   // and list coherency traffic, but also tends to increase the
  1027   // and list coherency traffic, but also tends to increase the
  1029   // number of objectMonitors in circulation as well as the STW
  1028   // number of objectMonitors in circulation as well as the STW
  1030   // scavenge costs.  As usual, we lean toward time in space-time
  1029   // scavenge costs.  As usual, we lean toward time in space-time
  1031   // tradeoffs.
  1030   // tradeoffs.
  1032   const int MAXPRIVATE = 1024;
  1031   const int MAXPRIVATE = 1024;
       
  1032   stringStream ss;
  1033   for (;;) {
  1033   for (;;) {
  1034     ObjectMonitor * m;
  1034     ObjectMonitor * m;
  1035 
  1035 
  1036     // 1: try to allocate from the thread's local omFreeList.
  1036     // 1: try to allocate from the thread's local omFreeList.
  1037     // Threads will attempt to allocate first from their local list, then
  1037     // Threads will attempt to allocate first from their local list, then
  1063       for (int i = Self->omFreeProvision; --i >= 0 && gFreeList != NULL;) {
  1063       for (int i = Self->omFreeProvision; --i >= 0 && gFreeList != NULL;) {
  1064         gMonitorFreeCount--;
  1064         gMonitorFreeCount--;
  1065         ObjectMonitor * take = gFreeList;
  1065         ObjectMonitor * take = gFreeList;
  1066         gFreeList = take->FreeNext;
  1066         gFreeList = take->FreeNext;
  1067         guarantee(take->object() == NULL, "invariant");
  1067         guarantee(take->object() == NULL, "invariant");
  1068         guarantee(!take->is_busy(), "invariant");
       
  1069         take->Recycle();
  1068         take->Recycle();
  1070         omRelease(Self, take, false);
  1069         omRelease(Self, take, false);
  1071       }
  1070       }
  1072       Thread::muxRelease(&gListLock);
  1071       Thread::muxRelease(&gListLock);
  1073       Self->omFreeProvision += 1 + (Self->omFreeProvision/2);
  1072       Self->omFreeProvision += 1 + (Self->omFreeProvision/2);
  1165 
  1164 
  1166 void ObjectSynchronizer::omRelease(Thread * Self, ObjectMonitor * m,
  1165 void ObjectSynchronizer::omRelease(Thread * Self, ObjectMonitor * m,
  1167                                    bool fromPerThreadAlloc) {
  1166                                    bool fromPerThreadAlloc) {
  1168   guarantee(m->header() == NULL, "invariant");
  1167   guarantee(m->header() == NULL, "invariant");
  1169   guarantee(m->object() == NULL, "invariant");
  1168   guarantee(m->object() == NULL, "invariant");
  1170   guarantee(((m->is_busy()|m->_recursions) == 0), "freeing in-use monitor");
  1169   stringStream ss;
       
  1170   guarantee((m->is_busy() | m->_recursions) == 0, "freeing in-use monitor: "
       
  1171             "%s, recursions=" INTPTR_FORMAT, m->is_busy_to_string(&ss),
       
  1172             m->_recursions);
  1171   // Remove from omInUseList
  1173   // Remove from omInUseList
  1172   if (fromPerThreadAlloc) {
  1174   if (fromPerThreadAlloc) {
  1173     ObjectMonitor* cur_mid_in_use = NULL;
  1175     ObjectMonitor* cur_mid_in_use = NULL;
  1174     bool extracted = false;
  1176     bool extracted = false;
  1175     for (ObjectMonitor* mid = Self->omInUseList; mid != NULL; cur_mid_in_use = mid, mid = mid->FreeNext) {
  1177     for (ObjectMonitor* mid = Self->omInUseList; mid != NULL; cur_mid_in_use = mid, mid = mid->FreeNext) {
  1218   ObjectMonitor * list = Self->omFreeList;  // Null-terminated SLL
  1220   ObjectMonitor * list = Self->omFreeList;  // Null-terminated SLL
  1219   ObjectMonitor * tail = NULL;
  1221   ObjectMonitor * tail = NULL;
  1220   int tally = 0;
  1222   int tally = 0;
  1221   if (list != NULL) {
  1223   if (list != NULL) {
  1222     ObjectMonitor * s;
  1224     ObjectMonitor * s;
  1223     // The thread is going away, the per-thread free monitors
  1225     // The thread is going away. Set 'tail' to the last per-thread free
  1224     // are freed via set_owner(NULL)
  1226     // monitor which will be linked to gFreeList below under the gListLock.
  1225     // Link them to tail, which will be linked into the global free list
  1227     stringStream ss;
  1226     // gFreeList below, under the gListLock
       
  1227     for (s = list; s != NULL; s = s->FreeNext) {
  1228     for (s = list; s != NULL; s = s->FreeNext) {
  1228       tally++;
  1229       tally++;
  1229       tail = s;
  1230       tail = s;
  1230       guarantee(s->object() == NULL, "invariant");
  1231       guarantee(s->object() == NULL, "invariant");
  1231       guarantee(!s->is_busy(), "invariant");
  1232       guarantee(!s->is_busy(), "must be !is_busy: %s", s->is_busy_to_string(&ss));
  1232       s->set_owner(NULL);   // redundant but good hygiene
       
  1233     }
  1233     }
  1234     guarantee(tail != NULL, "invariant");
  1234     guarantee(tail != NULL, "invariant");
  1235     assert(Self->omFreeCount == tally, "free-count off");
  1235     assert(Self->omFreeCount == tally, "free-count off");
  1236     Self->omFreeList = NULL;
  1236     Self->omFreeList = NULL;
  1237     Self->omFreeCount = 0;
  1237     Self->omFreeCount = 0;
  1377       // Optimistically prepare the objectmonitor - anticipate successful CAS
  1377       // Optimistically prepare the objectmonitor - anticipate successful CAS
  1378       // We do this before the CAS in order to minimize the length of time
  1378       // We do this before the CAS in order to minimize the length of time
  1379       // in which INFLATING appears in the mark.
  1379       // in which INFLATING appears in the mark.
  1380       m->Recycle();
  1380       m->Recycle();
  1381       m->_Responsible  = NULL;
  1381       m->_Responsible  = NULL;
  1382       m->_recursions   = 0;
       
  1383       m->_SpinDuration = ObjectMonitor::Knob_SpinLimit;   // Consider: maintain by type/class
  1382       m->_SpinDuration = ObjectMonitor::Knob_SpinLimit;   // Consider: maintain by type/class
  1384 
  1383 
  1385       markOop cmp = object->cas_set_mark(markOopDesc::INFLATING(), mark);
  1384       markOop cmp = object->cas_set_mark(markOopDesc::INFLATING(), mark);
  1386       if (cmp != mark) {
  1385       if (cmp != mark) {
  1387         omRelease(Self, m, true);
  1386         omRelease(Self, m, true);
  1470     assert(mark->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(mark));
  1469     assert(mark->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(mark));
  1471     ObjectMonitor * m = omAlloc(Self);
  1470     ObjectMonitor * m = omAlloc(Self);
  1472     // prepare m for installation - set monitor to initial state
  1471     // prepare m for installation - set monitor to initial state
  1473     m->Recycle();
  1472     m->Recycle();
  1474     m->set_header(mark);
  1473     m->set_header(mark);
  1475     m->set_owner(NULL);
       
  1476     m->set_object(object);
  1474     m->set_object(object);
  1477     m->_recursions   = 0;
       
  1478     m->_Responsible  = NULL;
  1475     m->_Responsible  = NULL;
  1479     m->_SpinDuration = ObjectMonitor::Knob_SpinLimit;       // consider: keep metastats by type/class
  1476     m->_SpinDuration = ObjectMonitor::Knob_SpinLimit;       // consider: keep metastats by type/class
  1480 
  1477 
  1481     if (object->cas_set_mark(markOopDesc::encode(m), mark) != mark) {
  1478     if (object->cas_set_mark(markOopDesc::encode(m), mark) != mark) {
  1482       m->set_header(NULL);
  1479       m->set_header(NULL);
  1923 }
  1920 }
  1924 
  1921 
  1925 // Check a free monitor entry; log any errors.
  1922 // Check a free monitor entry; log any errors.
  1926 void ObjectSynchronizer::chk_free_entry(JavaThread * jt, ObjectMonitor * n,
  1923 void ObjectSynchronizer::chk_free_entry(JavaThread * jt, ObjectMonitor * n,
  1927                                         outputStream * out, int *error_cnt_p) {
  1924                                         outputStream * out, int *error_cnt_p) {
       
  1925   stringStream ss;
  1928   if (n->is_busy()) {
  1926   if (n->is_busy()) {
  1929     if (jt != NULL) {
  1927     if (jt != NULL) {
  1930       out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT
  1928       out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT
  1931                     ": free per-thread monitor must not be busy.", p2i(jt),
  1929                     ": free per-thread monitor must not be busy: %s", p2i(jt),
  1932                     p2i(n));
  1930                     p2i(n), n->is_busy_to_string(&ss));
  1933     } else {
  1931     } else {
  1934       out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": free global monitor "
  1932       out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": free global monitor "
  1935                     "must not be busy.", p2i(n));
  1933                     "must not be busy: %s", p2i(n), n->is_busy_to_string(&ss));
  1936     }
  1934     }
  1937     *error_cnt_p = *error_cnt_p + 1;
  1935     *error_cnt_p = *error_cnt_p + 1;
  1938   }
  1936   }
  1939   if (n->header() != NULL) {
  1937   if (n->header() != NULL) {
  1940     if (jt != NULL) {
  1938     if (jt != NULL) {
  2109   if (!on_exit) {
  2107   if (!on_exit) {
  2110     // Not at VM exit so grab the global list lock.
  2108     // Not at VM exit so grab the global list lock.
  2111     Thread::muxAcquire(&gListLock, "log_in_use_monitor_details");
  2109     Thread::muxAcquire(&gListLock, "log_in_use_monitor_details");
  2112   }
  2110   }
  2113 
  2111 
       
  2112   stringStream ss;
  2114   if (gOmInUseCount > 0) {
  2113   if (gOmInUseCount > 0) {
  2115     out->print_cr("In-use global monitor info:");
  2114     out->print_cr("In-use global monitor info:");
  2116     out->print_cr("(B -> is_busy, H -> has hash code, L -> lock status)");
  2115     out->print_cr("(B -> is_busy, H -> has hash code, L -> lock status)");
  2117     out->print_cr("%18s  %s  %18s  %18s",
  2116     out->print_cr("%18s  %s  %18s  %18s",
  2118                   "monitor", "BHL", "object", "object type");
  2117                   "monitor", "BHL", "object", "object type");
  2119     out->print_cr("==================  ===  ==================  ==================");
  2118     out->print_cr("==================  ===  ==================  ==================");
  2120     for (ObjectMonitor * n = gOmInUseList; n != NULL; n = n->FreeNext) {
  2119     for (ObjectMonitor * n = gOmInUseList; n != NULL; n = n->FreeNext) {
  2121       const oop obj = (oop) n->object();
  2120       const oop obj = (oop) n->object();
  2122       const markOop mark = n->header();
  2121       const markOop mark = n->header();
  2123       ResourceMark rm;
  2122       ResourceMark rm;
  2124       out->print_cr(INTPTR_FORMAT "  %d%d%d  " INTPTR_FORMAT "  %s", p2i(n),
  2123       out->print(INTPTR_FORMAT "  %d%d%d  " INTPTR_FORMAT "  %s", p2i(n),
  2125                     n->is_busy() != 0, mark->hash() != 0, n->owner() != NULL,
  2124                  n->is_busy() != 0, mark->hash() != 0, n->owner() != NULL,
  2126                     p2i(obj), obj->klass()->external_name());
  2125                  p2i(obj), obj->klass()->external_name());
       
  2126       if (n->is_busy() != 0) {
       
  2127         out->print(" (%s)", n->is_busy_to_string(&ss));
       
  2128         ss.reset();
       
  2129       }
       
  2130       out->cr();
  2127     }
  2131     }
  2128   }
  2132   }
  2129 
  2133 
  2130   if (!on_exit) {
  2134   if (!on_exit) {
  2131     Thread::muxRelease(&gListLock);
  2135     Thread::muxRelease(&gListLock);
  2139   for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
  2143   for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
  2140     for (ObjectMonitor * n = jt->omInUseList; n != NULL; n = n->FreeNext) {
  2144     for (ObjectMonitor * n = jt->omInUseList; n != NULL; n = n->FreeNext) {
  2141       const oop obj = (oop) n->object();
  2145       const oop obj = (oop) n->object();
  2142       const markOop mark = n->header();
  2146       const markOop mark = n->header();
  2143       ResourceMark rm;
  2147       ResourceMark rm;
  2144       out->print_cr(INTPTR_FORMAT "  " INTPTR_FORMAT "  %d%d%d  " INTPTR_FORMAT
  2148       out->print(INTPTR_FORMAT "  " INTPTR_FORMAT "  %d%d%d  " INTPTR_FORMAT
  2145                     "  %s", p2i(jt), p2i(n), n->is_busy() != 0,
  2149                  "  %s", p2i(jt), p2i(n), n->is_busy() != 0,
  2146                     mark->hash() != 0, n->owner() != NULL, p2i(obj),
  2150                  mark->hash() != 0, n->owner() != NULL, p2i(obj),
  2147                     obj->klass()->external_name());
  2151                  obj->klass()->external_name());
       
  2152       if (n->is_busy() != 0) {
       
  2153         out->print(" (%s)", n->is_busy_to_string(&ss));
       
  2154         ss.reset();
       
  2155       }
       
  2156       out->cr();
  2148     }
  2157     }
  2149   }
  2158   }
  2150 
  2159 
  2151   out->flush();
  2160   out->flush();
  2152 }
  2161 }