jdk/src/share/classes/java/util/concurrent/locks/StampedLock.java
changeset 19589 459db4bb1df0
parent 18576 7a5c231327af
equal deleted inserted replaced
19588:5f7c7cdd74e9 19589:459db4bb1df0
   224      * Anderson, especially http://www.cs.unc.edu/~bbb/diss/).  In
   224      * Anderson, especially http://www.cs.unc.edu/~bbb/diss/).  In
   225      * particular, we use the phase-fair anti-barging rule: If an
   225      * particular, we use the phase-fair anti-barging rule: If an
   226      * incoming reader arrives while read lock is held but there is a
   226      * incoming reader arrives while read lock is held but there is a
   227      * queued writer, this incoming reader is queued.  (This rule is
   227      * queued writer, this incoming reader is queued.  (This rule is
   228      * responsible for some of the complexity of method acquireRead,
   228      * responsible for some of the complexity of method acquireRead,
   229      * but without it, the lock becomes highly unfair.)
   229      * but without it, the lock becomes highly unfair.) Method release
       
   230      * does not (and sometimes cannot) itself wake up cowaiters. This
       
   231      * is done by the primary thread, but helped by any other threads
       
   232      * with nothing better to do in methods acquireRead and
       
   233      * acquireWrite.
   230      *
   234      *
   231      * These rules apply to threads actually queued. All tryLock forms
   235      * These rules apply to threads actually queued. All tryLock forms
   232      * opportunistically try to acquire locks regardless of preference
   236      * opportunistically try to acquire locks regardless of preference
   233      * rules, and so may "barge" their way in.  Randomized spinning is
   237      * rules, and so may "barge" their way in.  Randomized spinning is
   234      * used in the acquire methods to reduce (increasingly expensive)
   238      * used in the acquire methods to reduce (increasingly expensive)
   265     private static final long serialVersionUID = -6001602636862214147L;
   269     private static final long serialVersionUID = -6001602636862214147L;
   266 
   270 
   267     /** Number of processors, for spin control */
   271     /** Number of processors, for spin control */
   268     private static final int NCPU = Runtime.getRuntime().availableProcessors();
   272     private static final int NCPU = Runtime.getRuntime().availableProcessors();
   269 
   273 
   270     /** Maximum number of retries before blocking on acquisition */
   274     /** Maximum number of retries before enqueuing on acquisition */
   271     private static final int SPINS = (NCPU > 1) ? 1 << 6 : 0;
   275     private static final int SPINS = (NCPU > 1) ? 1 << 6 : 0;
   272 
   276 
       
   277     /** Maximum number of retries before blocking at head on acquisition */
       
   278     private static final int HEAD_SPINS = (NCPU > 1) ? 1 << 10 : 0;
       
   279 
   273     /** Maximum number of retries before re-blocking */
   280     /** Maximum number of retries before re-blocking */
   274     private static final int MAX_HEAD_SPINS = (NCPU > 1) ? 1 << 12 : 0;
   281     private static final int MAX_HEAD_SPINS = (NCPU > 1) ? 1 << 16 : 0;
   275 
   282 
   276     /** The period for yielding when waiting for overflow spinlock */
   283     /** The period for yielding when waiting for overflow spinlock */
   277     private static final int OVERFLOW_YIELD_RATE = 7; // must be power 2 - 1
   284     private static final int OVERFLOW_YIELD_RATE = 7; // must be power 2 - 1
   278 
   285 
   279     /** The number of bits to use for reader count before overflowing */
   286     /** The number of bits to use for reader count before overflowing */
   413      * until available.
   420      * until available.
   414      *
   421      *
   415      * @return a stamp that can be used to unlock or convert mode
   422      * @return a stamp that can be used to unlock or convert mode
   416      */
   423      */
   417     public long readLock() {
   424     public long readLock() {
   418         long s, next;  // bypass acquireRead on fully unlocked case only
   425         long s = state, next;  // bypass acquireRead on common uncontended case
   419         return ((((s = state) & ABITS) == 0L &&
   426         return ((whead == wtail && (s & ABITS) < RFULL &&
   420                  U.compareAndSwapLong(this, STATE, s, next = s + RUNIT)) ?
   427                  U.compareAndSwapLong(this, STATE, s, next = s + RUNIT)) ?
   421                 next : acquireRead(false, 0L));
   428                 next : acquireRead(false, 0L));
   422     }
   429     }
   423 
   430 
   424     /**
   431     /**
  1010             if ((q = h.next) == null || q.status == CANCELLED) {
  1017             if ((q = h.next) == null || q.status == CANCELLED) {
  1011                 for (WNode t = wtail; t != null && t != h; t = t.prev)
  1018                 for (WNode t = wtail; t != null && t != h; t = t.prev)
  1012                     if (t.status <= 0)
  1019                     if (t.status <= 0)
  1013                         q = t;
  1020                         q = t;
  1014             }
  1021             }
  1015             if (q != null) {
  1022             if (q != null && (w = q.thread) != null)
  1016                 for (WNode r = q;;) {  // release co-waiters too
  1023                 U.unpark(w);
  1017                     if ((w = r.thread) != null) {
       
  1018                         r.thread = null;
       
  1019                         U.unpark(w);
       
  1020                     }
       
  1021                     if ((r = q.cowait) == null)
       
  1022                         break;
       
  1023                     U.compareAndSwapObject(q, WCOWAIT, r, r.cowait);
       
  1024                 }
       
  1025             }
       
  1026         }
  1024         }
  1027     }
  1025     }
  1028 
  1026 
  1029     /**
  1027     /**
  1030      * See above for explanation.
  1028      * See above for explanation.
  1036      * @return next state, or INTERRUPTED
  1034      * @return next state, or INTERRUPTED
  1037      */
  1035      */
  1038     private long acquireWrite(boolean interruptible, long deadline) {
  1036     private long acquireWrite(boolean interruptible, long deadline) {
  1039         WNode node = null, p;
  1037         WNode node = null, p;
  1040         for (int spins = -1;;) { // spin while enqueuing
  1038         for (int spins = -1;;) { // spin while enqueuing
  1041             long s, ns;
  1039             long m, s, ns;
  1042             if (((s = state) & ABITS) == 0L) {
  1040             if ((m = (s = state) & ABITS) == 0L) {
  1043                 if (U.compareAndSwapLong(this, STATE, s, ns = s + WBIT))
  1041                 if (U.compareAndSwapLong(this, STATE, s, ns = s + WBIT))
  1044                     return ns;
  1042                     return ns;
  1045             }
  1043             }
       
  1044             else if (spins < 0)
       
  1045                 spins = (m == WBIT && wtail == whead) ? SPINS : 0;
  1046             else if (spins > 0) {
  1046             else if (spins > 0) {
  1047                 if (LockSupport.nextSecondarySeed() >= 0)
  1047                 if (LockSupport.nextSecondarySeed() >= 0)
  1048                     --spins;
  1048                     --spins;
  1049             }
  1049             }
  1050             else if ((p = wtail) == null) { // initialize queue
  1050             else if ((p = wtail) == null) { // initialize queue
  1051                 WNode h = new WNode(WMODE, null);
  1051                 WNode hd = new WNode(WMODE, null);
  1052                 if (U.compareAndSwapObject(this, WHEAD, null, h))
  1052                 if (U.compareAndSwapObject(this, WHEAD, null, hd))
  1053                     wtail = h;
  1053                     wtail = hd;
  1054             }
  1054             }
  1055             else if (spins < 0)
       
  1056                 spins = (p == whead) ? SPINS : 0;
       
  1057             else if (node == null)
  1055             else if (node == null)
  1058                 node = new WNode(WMODE, p);
  1056                 node = new WNode(WMODE, p);
  1059             else if (node.prev != p)
  1057             else if (node.prev != p)
  1060                 node.prev = p;
  1058                 node.prev = p;
  1061             else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
  1059             else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
  1062                 p.next = node;
  1060                 p.next = node;
  1063                 break;
  1061                 break;
  1064             }
  1062             }
  1065         }
  1063         }
  1066 
  1064 
  1067         for (int spins = SPINS;;) {
  1065         for (int spins = -1;;) {
  1068             WNode np, pp; int ps; long s, ns; Thread w;
  1066             WNode h, np, pp; int ps;
  1069             while ((np = node.prev) != p && np != null)
  1067             if ((h = whead) == p) {
  1070                 (p = np).next = node;   // stale
  1068                 if (spins < 0)
  1071             if (whead == p) {
  1069                     spins = HEAD_SPINS;
       
  1070                 else if (spins < MAX_HEAD_SPINS)
       
  1071                     spins <<= 1;
  1072                 for (int k = spins;;) { // spin at head
  1072                 for (int k = spins;;) { // spin at head
       
  1073                     long s, ns;
  1073                     if (((s = state) & ABITS) == 0L) {
  1074                     if (((s = state) & ABITS) == 0L) {
  1074                         if (U.compareAndSwapLong(this, STATE, s, ns = s+WBIT)) {
  1075                         if (U.compareAndSwapLong(this, STATE, s,
       
  1076                                                  ns = s + WBIT)) {
  1075                             whead = node;
  1077                             whead = node;
  1076                             node.prev = null;
  1078                             node.prev = null;
  1077                             return ns;
  1079                             return ns;
  1078                         }
  1080                         }
  1079                     }
  1081                     }
  1080                     else if (LockSupport.nextSecondarySeed() >= 0 &&
  1082                     else if (LockSupport.nextSecondarySeed() >= 0 &&
  1081                              --k <= 0)
  1083                              --k <= 0)
  1082                         break;
  1084                         break;
  1083                 }
  1085                 }
  1084                 if (spins < MAX_HEAD_SPINS)
  1086             }
  1085                     spins <<= 1;
  1087             else if (h != null) { // help release stale waiters
  1086             }
  1088                 WNode c; Thread w;
  1087             if ((ps = p.status) == 0)
  1089                 while ((c = h.cowait) != null) {
  1088                 U.compareAndSwapInt(p, WSTATUS, 0, WAITING);
  1090                     if (U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
  1089             else if (ps == CANCELLED) {
  1091                         (w = c.thread) != null)
  1090                 if ((pp = p.prev) != null) {
  1092                         U.unpark(w);
  1091                     node.prev = pp;
  1093                 }
  1092                     pp.next = node;
  1094             }
  1093                 }
  1095             if (whead == h) {
  1094             }
  1096                 if ((np = node.prev) != p) {
  1095             else {
  1097                     if (np != null)
  1096                 long time; // 0 argument to park means no timeout
  1098                         (p = np).next = node;   // stale
  1097                 if (deadline == 0L)
  1099                 }
  1098                     time = 0L;
  1100                 else if ((ps = p.status) == 0)
  1099                 else if ((time = deadline - System.nanoTime()) <= 0L)
  1101                     U.compareAndSwapInt(p, WSTATUS, 0, WAITING);
  1100                     return cancelWaiter(node, node, false);
  1102                 else if (ps == CANCELLED) {
  1101                 Thread wt = Thread.currentThread();
  1103                     if ((pp = p.prev) != null) {
  1102                 U.putObject(wt, PARKBLOCKER, this); // emulate LockSupport.park
  1104                         node.prev = pp;
  1103                 node.thread = wt;
  1105                         pp.next = node;
  1104                 if (node.prev == p && p.status == WAITING && // recheck
  1106                     }
  1105                     (p != whead || (state & ABITS) != 0L))
  1107                 }
  1106                     U.park(false, time);
  1108                 else {
  1107                 node.thread = null;
  1109                     long time; // 0 argument to park means no timeout
  1108                 U.putObject(wt, PARKBLOCKER, null);
  1110                     if (deadline == 0L)
  1109                 if (interruptible && Thread.interrupted())
  1111                         time = 0L;
  1110                     return cancelWaiter(node, node, true);
  1112                     else if ((time = deadline - System.nanoTime()) <= 0L)
       
  1113                         return cancelWaiter(node, node, false);
       
  1114                     Thread wt = Thread.currentThread();
       
  1115                     U.putObject(wt, PARKBLOCKER, this);
       
  1116                     node.thread = wt;
       
  1117                     if (p.status < 0 && (p != h || (state & ABITS) != 0L) &&
       
  1118                         whead == h && node.prev == p)
       
  1119                         U.park(false, time);  // emulate LockSupport.park
       
  1120                     node.thread = null;
       
  1121                     U.putObject(wt, PARKBLOCKER, null);
       
  1122                     if (interruptible && Thread.interrupted())
       
  1123                         return cancelWaiter(node, node, true);
       
  1124                 }
  1111             }
  1125             }
  1112         }
  1126         }
  1113     }
  1127     }
  1114 
  1128 
  1115     /**
  1129     /**
  1120      * @param deadline if nonzero, the System.nanoTime value to timeout
  1134      * @param deadline if nonzero, the System.nanoTime value to timeout
  1121      * at (and return zero)
  1135      * at (and return zero)
  1122      * @return next state, or INTERRUPTED
  1136      * @return next state, or INTERRUPTED
  1123      */
  1137      */
  1124     private long acquireRead(boolean interruptible, long deadline) {
  1138     private long acquireRead(boolean interruptible, long deadline) {
  1125         WNode node = null, group = null, p;
  1139         WNode node = null, p;
  1126         for (int spins = -1;;) {
  1140         for (int spins = -1;;) {
  1127             for (;;) {
  1141             WNode h;
  1128                 long s, m, ns; WNode h, q; Thread w; // anti-barging guard
  1142             if ((h = whead) == (p = wtail)) {
  1129                 if (group == null && (h = whead) != null &&
  1143                 for (long m, s, ns;;) {
  1130                     (q = h.next) != null && q.mode != RMODE)
  1144                     if ((m = (s = state) & ABITS) < RFULL ?
  1131                     break;
  1145                         U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) :
  1132                 if ((m = (s = state) & ABITS) < RFULL ?
  1146                         (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L))
  1133                     U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) :
  1147                         return ns;
  1134                     (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L)) {
  1148                     else if (m >= WBIT) {
  1135                     if (group != null) {  // help release others
  1149                         if (spins > 0) {
  1136                         for (WNode r = group;;) {
  1150                             if (LockSupport.nextSecondarySeed() >= 0)
  1137                             if ((w = r.thread) != null) {
  1151                                 --spins;
  1138                                 r.thread = null;
  1152                         }
  1139                                 U.unpark(w);
  1153                         else {
       
  1154                             if (spins == 0) {
       
  1155                                 WNode nh = whead, np = wtail;
       
  1156                                 if ((nh == h && np == p) || (h = nh) != (p = np))
       
  1157                                     break;
  1140                             }
  1158                             }
  1141                             if ((r = group.cowait) == null)
  1159                             spins = SPINS;
  1142                                 break;
       
  1143                             U.compareAndSwapObject(group, WCOWAIT, r, r.cowait);
       
  1144                         }
  1160                         }
  1145                     }
  1161                     }
  1146                     return ns;
  1162                 }
  1147                 }
  1163             }
  1148                 if (m >= WBIT)
  1164             if (p == null) { // initialize queue
       
  1165                 WNode hd = new WNode(WMODE, null);
       
  1166                 if (U.compareAndSwapObject(this, WHEAD, null, hd))
       
  1167                     wtail = hd;
       
  1168             }
       
  1169             else if (node == null)
       
  1170                 node = new WNode(RMODE, p);
       
  1171             else if (h == p || p.mode != RMODE) {
       
  1172                 if (node.prev != p)
       
  1173                     node.prev = p;
       
  1174                 else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
       
  1175                     p.next = node;
  1149                     break;
  1176                     break;
  1150             }
  1177                 }
  1151             if (spins > 0) {
  1178             }
  1152                 if (LockSupport.nextSecondarySeed() >= 0)
  1179             else if (!U.compareAndSwapObject(p, WCOWAIT,
  1153                     --spins;
  1180                                              node.cowait = p.cowait, node))
  1154             }
  1181                 node.cowait = null;
  1155             else if ((p = wtail) == null) {
  1182             else {
  1156                 WNode h = new WNode(WMODE, null);
  1183                 for (;;) {
  1157                 if (U.compareAndSwapObject(this, WHEAD, null, h))
  1184                     WNode pp, c; Thread w;
  1158                     wtail = h;
  1185                     if ((h = whead) != null && (c = h.cowait) != null &&
  1159             }
  1186                         U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
  1160             else if (spins < 0)
  1187                         (w = c.thread) != null) // help release
  1161                 spins = (p == whead) ? SPINS : 0;
  1188                         U.unpark(w);
  1162             else if (node == null)
  1189                     if (h == (pp = p.prev) || h == p || pp == null) {
  1163                 node = new WNode(WMODE, p);
  1190                         long m, s, ns;
  1164             else if (node.prev != p)
  1191                         do {
  1165                 node.prev = p;
  1192                             if ((m = (s = state) & ABITS) < RFULL ?
  1166             else if (p.mode == RMODE && p != whead) {
  1193                                 U.compareAndSwapLong(this, STATE, s,
  1167                 WNode pp = p.prev;  // become co-waiter with group p
  1194                                                      ns = s + RUNIT) :
  1168                 if (pp != null && p == wtail &&
  1195                                 (m < WBIT &&
  1169                     U.compareAndSwapObject(p, WCOWAIT,
  1196                                  (ns = tryIncReaderOverflow(s)) != 0L))
  1170                                            node.cowait = p.cowait, node)) {
  1197                                 return ns;
  1171                     node.thread = Thread.currentThread();
  1198                         } while (m < WBIT);
  1172                     for (long time;;) {
  1199                     }
       
  1200                     if (whead == h && p.prev == pp) {
       
  1201                         long time;
       
  1202                         if (pp == null || h == p || p.status > 0) {
       
  1203                             node = null; // throw away
       
  1204                             break;
       
  1205                         }
  1173                         if (deadline == 0L)
  1206                         if (deadline == 0L)
  1174                             time = 0L;
  1207                             time = 0L;
  1175                         else if ((time = deadline - System.nanoTime()) <= 0L)
  1208                         else if ((time = deadline - System.nanoTime()) <= 0L)
  1176                             return cancelWaiter(node, p, false);
  1209                             return cancelWaiter(node, p, false);
  1177                         if (node.thread == null)
       
  1178                             break;
       
  1179                         if (p.prev != pp || p.status == CANCELLED ||
       
  1180                             p == whead || p.prev != pp) {
       
  1181                             node.thread = null;
       
  1182                             break;
       
  1183                         }
       
  1184                         Thread wt = Thread.currentThread();
  1210                         Thread wt = Thread.currentThread();
  1185                         U.putObject(wt, PARKBLOCKER, this);
  1211                         U.putObject(wt, PARKBLOCKER, this);
  1186                         if (node.thread == null) // must recheck
  1212                         node.thread = wt;
  1187                             break;
  1213                         if ((h != pp || (state & ABITS) == WBIT) &&
  1188                         U.park(false, time);
  1214                             whead == h && p.prev == pp)
       
  1215                             U.park(false, time);
       
  1216                         node.thread = null;
  1189                         U.putObject(wt, PARKBLOCKER, null);
  1217                         U.putObject(wt, PARKBLOCKER, null);
  1190                         if (interruptible && Thread.interrupted())
  1218                         if (interruptible && Thread.interrupted())
  1191                             return cancelWaiter(node, p, true);
  1219                             return cancelWaiter(node, p, true);
  1192                     }
  1220                     }
  1193                     group = p;
  1221                 }
  1194                 }
  1222             }
  1195                 node = null; // throw away
  1223         }
  1196             }
  1224 
  1197             else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
  1225         for (int spins = -1;;) {
  1198                 p.next = node;
  1226             WNode h, np, pp; int ps;
  1199                 break;
  1227             if ((h = whead) == p) {
  1200             }
  1228                 if (spins < 0)
  1201         }
  1229                     spins = HEAD_SPINS;
  1202 
  1230                 else if (spins < MAX_HEAD_SPINS)
  1203         for (int spins = SPINS;;) {
  1231                     spins <<= 1;
  1204             WNode np, pp, r; int ps; long m, s, ns; Thread w;
  1232                 for (int k = spins;;) { // spin at head
  1205             while ((np = node.prev) != p && np != null)
  1233                     long m, s, ns;
  1206                 (p = np).next = node;
  1234                     if ((m = (s = state) & ABITS) < RFULL ?
  1207             if (whead == p) {
  1235                         U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) :
  1208                 for (int k = spins;;) {
  1236                         (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L)) {
  1209                     if ((m = (s = state) & ABITS) != WBIT) {
  1237                         WNode c; Thread w;
  1210                         if (m < RFULL ?
  1238                         whead = node;
  1211                             U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT):
  1239                         node.prev = null;
  1212                             (ns = tryIncReaderOverflow(s)) != 0L) {
  1240                         while ((c = node.cowait) != null) {
  1213                             whead = node;
  1241                             if (U.compareAndSwapObject(node, WCOWAIT,
  1214                             node.prev = null;
  1242                                                        c, c.cowait) &&
  1215                             while ((r = node.cowait) != null) {
  1243                                 (w = c.thread) != null)
  1216                                 if (U.compareAndSwapObject(node, WCOWAIT,
  1244                                 U.unpark(w);
  1217                                                            r, r.cowait) &&
       
  1218                                     (w = r.thread) != null) {
       
  1219                                     r.thread = null;
       
  1220                                     U.unpark(w); // release co-waiter
       
  1221                                 }
       
  1222                             }
       
  1223                             return ns;
       
  1224                         }
  1245                         }
       
  1246                         return ns;
  1225                     }
  1247                     }
  1226                     else if (LockSupport.nextSecondarySeed() >= 0 &&
  1248                     else if (m >= WBIT &&
  1227                              --k <= 0)
  1249                              LockSupport.nextSecondarySeed() >= 0 && --k <= 0)
  1228                         break;
  1250                         break;
  1229                 }
  1251                 }
  1230                 if (spins < MAX_HEAD_SPINS)
  1252             }
  1231                     spins <<= 1;
  1253             else if (h != null) {
  1232             }
  1254                 WNode c; Thread w;
  1233             if ((ps = p.status) == 0)
  1255                 while ((c = h.cowait) != null) {
  1234                 U.compareAndSwapInt(p, WSTATUS, 0, WAITING);
  1256                     if (U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
  1235             else if (ps == CANCELLED) {
  1257                         (w = c.thread) != null)
  1236                 if ((pp = p.prev) != null) {
  1258                         U.unpark(w);
  1237                     node.prev = pp;
  1259                 }
  1238                     pp.next = node;
  1260             }
  1239                 }
  1261             if (whead == h) {
  1240             }
  1262                 if ((np = node.prev) != p) {
  1241             else {
  1263                     if (np != null)
  1242                 long time;
  1264                         (p = np).next = node;   // stale
  1243                 if (deadline == 0L)
  1265                 }
  1244                     time = 0L;
  1266                 else if ((ps = p.status) == 0)
  1245                 else if ((time = deadline - System.nanoTime()) <= 0L)
  1267                     U.compareAndSwapInt(p, WSTATUS, 0, WAITING);
  1246                     return cancelWaiter(node, node, false);
  1268                 else if (ps == CANCELLED) {
  1247                 Thread wt = Thread.currentThread();
  1269                     if ((pp = p.prev) != null) {
  1248                 U.putObject(wt, PARKBLOCKER, this);
  1270                         node.prev = pp;
  1249                 node.thread = wt;
  1271                         pp.next = node;
  1250                 if (node.prev == p && p.status == WAITING &&
  1272                     }
  1251                     (p != whead || (state & ABITS) != WBIT))
  1273                 }
  1252                     U.park(false, time);
  1274                 else {
  1253                 node.thread = null;
  1275                     long time;
  1254                 U.putObject(wt, PARKBLOCKER, null);
  1276                     if (deadline == 0L)
  1255                 if (interruptible && Thread.interrupted())
  1277                         time = 0L;
  1256                     return cancelWaiter(node, node, true);
  1278                     else if ((time = deadline - System.nanoTime()) <= 0L)
       
  1279                         return cancelWaiter(node, node, false);
       
  1280                     Thread wt = Thread.currentThread();
       
  1281                     U.putObject(wt, PARKBLOCKER, this);
       
  1282                     node.thread = wt;
       
  1283                     if (p.status < 0 &&
       
  1284                         (p != h || (state & ABITS) == WBIT) &&
       
  1285                         whead == h && node.prev == p)
       
  1286                         U.park(false, time);
       
  1287                     node.thread = null;
       
  1288                     U.putObject(wt, PARKBLOCKER, null);
       
  1289                     if (interruptible && Thread.interrupted())
       
  1290                         return cancelWaiter(node, node, true);
       
  1291                 }
  1257             }
  1292             }
  1258         }
  1293         }
  1259     }
  1294     }
  1260 
  1295 
  1261     /**
  1296     /**
  1276      */
  1311      */
  1277     private long cancelWaiter(WNode node, WNode group, boolean interrupted) {
  1312     private long cancelWaiter(WNode node, WNode group, boolean interrupted) {
  1278         if (node != null && group != null) {
  1313         if (node != null && group != null) {
  1279             Thread w;
  1314             Thread w;
  1280             node.status = CANCELLED;
  1315             node.status = CANCELLED;
  1281             node.thread = null;
       
  1282             // unsplice cancelled nodes from group
  1316             // unsplice cancelled nodes from group
  1283             for (WNode p = group, q; (q = p.cowait) != null;) {
  1317             for (WNode p = group, q; (q = p.cowait) != null;) {
  1284                 if (q.status == CANCELLED)
  1318                 if (q.status == CANCELLED) {
  1285                     U.compareAndSwapObject(p, WNEXT, q, q.next);
  1319                     U.compareAndSwapObject(p, WCOWAIT, q, q.cowait);
       
  1320                     p = group; // restart
       
  1321                 }
  1286                 else
  1322                 else
  1287                     p = q;
  1323                     p = q;
  1288             }
  1324             }
  1289             if (group == node) {
  1325             if (group == node) {
  1290                 WNode r; // detach and wake up uncancelled co-waiters
  1326                 for (WNode r = group.cowait; r != null; r = r.cowait) {
  1291                 while ((r = node.cowait) != null) {
  1327                     if ((w = r.thread) != null)
  1292                     if (U.compareAndSwapObject(node, WCOWAIT, r, r.cowait) &&
  1328                         U.unpark(w);       // wake up uncancelled co-waiters
  1293                         (w = r.thread) != null) {
       
  1294                         r.thread = null;
       
  1295                         U.unpark(w);
       
  1296                     }
       
  1297                 }
  1329                 }
  1298                 for (WNode pred = node.prev; pred != null; ) { // unsplice
  1330                 for (WNode pred = node.prev; pred != null; ) { // unsplice
  1299                     WNode succ, pp;        // find valid successor
  1331                     WNode succ, pp;        // find valid successor
  1300                     while ((succ = node.next) == null ||
  1332                     while ((succ = node.next) == null ||
  1301                            succ.status == CANCELLED) {
  1333                            succ.status == CANCELLED) {