1.1 --- a/src/share/vm/runtime/park.cpp Fri Feb 14 09:50:17 2014 -0800 1.2 +++ b/src/share/vm/runtime/park.cpp Fri Jan 24 09:28:47 2014 +0100 1.3 @@ -59,58 +59,22 @@ 1.4 1.5 // Start by trying to recycle an existing but unassociated 1.6 // ParkEvent from the global free list. 1.7 - for (;;) { 1.8 - ev = FreeList ; 1.9 - if (ev == NULL) break ; 1.10 - // 1: Detach - sequester or privatize the list 1.11 - // Tantamount to ev = Swap (&FreeList, NULL) 1.12 - if (Atomic::cmpxchg_ptr (NULL, &FreeList, ev) != ev) { 1.13 - continue ; 1.14 + // Using a spin lock since we are part of the mutex impl. 1.15 + // 8028280: using concurrent free list without memory management can leak 1.16 + // pretty badly it turns out. 1.17 + Thread::SpinAcquire(&ListLock, "ParkEventFreeListAllocate"); 1.18 + { 1.19 + ev = FreeList; 1.20 + if (ev != NULL) { 1.21 + FreeList = ev->FreeNext; 1.22 } 1.23 - 1.24 - // We've detached the list. The list in-hand is now 1.25 - // local to this thread. This thread can operate on the 1.26 - // list without risk of interference from other threads. 1.27 - // 2: Extract -- pop the 1st element from the list. 1.28 - ParkEvent * List = ev->FreeNext ; 1.29 - if (List == NULL) break ; 1.30 - for (;;) { 1.31 - // 3: Try to reattach the residual list 1.32 - guarantee (List != NULL, "invariant") ; 1.33 - ParkEvent * Arv = (ParkEvent *) Atomic::cmpxchg_ptr (List, &FreeList, NULL) ; 1.34 - if (Arv == NULL) break ; 1.35 - 1.36 - // New nodes arrived. Try to detach the recent arrivals. 1.37 - if (Atomic::cmpxchg_ptr (NULL, &FreeList, Arv) != Arv) { 1.38 - continue ; 1.39 - } 1.40 - guarantee (Arv != NULL, "invariant") ; 1.41 - // 4: Merge Arv into List 1.42 - ParkEvent * Tail = List ; 1.43 - while (Tail->FreeNext != NULL) Tail = Tail->FreeNext ; 1.44 - Tail->FreeNext = Arv ; 1.45 - } 1.46 - break ; 1.47 } 1.48 + Thread::SpinRelease(&ListLock); 1.49 1.50 if (ev != NULL) { 1.51 guarantee (ev->AssociatedWith == NULL, "invariant") ; 1.52 } else { 1.53 // Do this the hard way -- materialize a new ParkEvent. 1.54 - // In rare cases an allocating thread might detach a long list -- 1.55 - // installing null into FreeList -- and then stall or be obstructed. 1.56 - // A 2nd thread calling Allocate() would see FreeList == null. 1.57 - // The list held privately by the 1st thread is unavailable to the 2nd thread. 1.58 - // In that case the 2nd thread would have to materialize a new ParkEvent, 1.59 - // even though free ParkEvents existed in the system. In this case we end up 1.60 - // with more ParkEvents in circulation than we need, but the race is 1.61 - // rare and the outcome is benign. Ideally, the # of extant ParkEvents 1.62 - // is equal to the maximum # of threads that existed at any one time. 1.63 - // Because of the race mentioned above, segments of the freelist 1.64 - // can be transiently inaccessible. At worst we may end up with the 1.65 - // # of ParkEvents in circulation slightly above the ideal. 1.66 - // Note that if we didn't have the TSM/immortal constraint, then 1.67 - // when reattaching, above, we could trim the list. 1.68 ev = new ParkEvent () ; 1.69 guarantee ((intptr_t(ev) & 0xFF) == 0, "invariant") ; 1.70 } 1.71 @@ -124,13 +88,14 @@ 1.72 if (ev == NULL) return ; 1.73 guarantee (ev->FreeNext == NULL , "invariant") ; 1.74 ev->AssociatedWith = NULL ; 1.75 - for (;;) { 1.76 - // Push ev onto FreeList 1.77 - // The mechanism is "half" lock-free. 1.78 - ParkEvent * List = FreeList ; 1.79 - ev->FreeNext = List ; 1.80 - if (Atomic::cmpxchg_ptr (ev, &FreeList, List) == List) break ; 1.81 + // Note that if we didn't have the TSM/immortal constraint, then 1.82 + // when reattaching we could trim the list. 1.83 + Thread::SpinAcquire(&ListLock, "ParkEventFreeListRelease"); 1.84 + { 1.85 + ev->FreeNext = FreeList; 1.86 + FreeList = ev; 1.87 } 1.88 + Thread::SpinRelease(&ListLock); 1.89 } 1.90 1.91 // Override operator new and delete so we can ensure that the 1.92 @@ -164,56 +129,21 @@ 1.93 1.94 // Start by trying to recycle an existing but unassociated 1.95 // Parker from the global free list. 1.96 - for (;;) { 1.97 - p = FreeList ; 1.98 - if (p == NULL) break ; 1.99 - // 1: Detach 1.100 - // Tantamount to p = Swap (&FreeList, NULL) 1.101 - if (Atomic::cmpxchg_ptr (NULL, &FreeList, p) != p) { 1.102 - continue ; 1.103 + // 8028280: using concurrent free list without memory management can leak 1.104 + // pretty badly it turns out. 1.105 + Thread::SpinAcquire(&ListLock, "ParkerFreeListAllocate"); 1.106 + { 1.107 + p = FreeList; 1.108 + if (p != NULL) { 1.109 + FreeList = p->FreeNext; 1.110 } 1.111 - 1.112 - // We've detached the list. The list in-hand is now 1.113 - // local to this thread. This thread can operate on the 1.114 - // list without risk of interference from other threads. 1.115 - // 2: Extract -- pop the 1st element from the list. 1.116 - Parker * List = p->FreeNext ; 1.117 - if (List == NULL) break ; 1.118 - for (;;) { 1.119 - // 3: Try to reattach the residual list 1.120 - guarantee (List != NULL, "invariant") ; 1.121 - Parker * Arv = (Parker *) Atomic::cmpxchg_ptr (List, &FreeList, NULL) ; 1.122 - if (Arv == NULL) break ; 1.123 - 1.124 - // New nodes arrived. Try to detach the recent arrivals. 1.125 - if (Atomic::cmpxchg_ptr (NULL, &FreeList, Arv) != Arv) { 1.126 - continue ; 1.127 - } 1.128 - guarantee (Arv != NULL, "invariant") ; 1.129 - // 4: Merge Arv into List 1.130 - Parker * Tail = List ; 1.131 - while (Tail->FreeNext != NULL) Tail = Tail->FreeNext ; 1.132 - Tail->FreeNext = Arv ; 1.133 - } 1.134 - break ; 1.135 } 1.136 + Thread::SpinRelease(&ListLock); 1.137 1.138 if (p != NULL) { 1.139 guarantee (p->AssociatedWith == NULL, "invariant") ; 1.140 } else { 1.141 // Do this the hard way -- materialize a new Parker.. 1.142 - // In rare cases an allocating thread might detach 1.143 - // a long list -- installing null into FreeList --and 1.144 - // then stall. Another thread calling Allocate() would see 1.145 - // FreeList == null and then invoke the ctor. In this case we 1.146 - // end up with more Parkers in circulation than we need, but 1.147 - // the race is rare and the outcome is benign. 1.148 - // Ideally, the # of extant Parkers is equal to the 1.149 - // maximum # of threads that existed at any one time. 1.150 - // Because of the race mentioned above, segments of the 1.151 - // freelist can be transiently inaccessible. At worst 1.152 - // we may end up with the # of Parkers in circulation 1.153 - // slightly above the ideal. 1.154 p = new Parker() ; 1.155 } 1.156 p->AssociatedWith = t ; // Associate p with t 1.157 @@ -227,11 +157,12 @@ 1.158 guarantee (p->AssociatedWith != NULL, "invariant") ; 1.159 guarantee (p->FreeNext == NULL , "invariant") ; 1.160 p->AssociatedWith = NULL ; 1.161 - for (;;) { 1.162 - // Push p onto FreeList 1.163 - Parker * List = FreeList ; 1.164 - p->FreeNext = List ; 1.165 - if (Atomic::cmpxchg_ptr (p, &FreeList, List) == List) break ; 1.166 + 1.167 + Thread::SpinAcquire(&ListLock, "ParkerFreeListRelease"); 1.168 + { 1.169 + p->FreeNext = FreeList; 1.170 + FreeList = p; 1.171 } 1.172 + Thread::SpinRelease(&ListLock); 1.173 } 1.174