< prev index next >

src/hotspot/share/gc/shared/taskqueue.inline.hpp

Print this page
rev 49680 : imported patch 6672778-partial-queue-trimming


 135   if (localBot == oldAge.top()) {
 136     // No competing pop_global has yet incremented "top"; we'll try to
 137     // install new_age, thus claiming the element.
 138     Age tempAge = _age.cmpxchg(newAge, oldAge);
 139     if (tempAge == oldAge) {
 140       // We win.
 141       assert(dirty_size(localBot, _age.top()) != N - 1, "sanity");
 142       TASKQUEUE_STATS_ONLY(stats.record_pop_slow());
 143       return true;
 144     }
 145   }
 146   // We lose; a completing pop_global gets the element.  But the queue is empty
 147   // and top is greater than bottom.  Fix this representation of the empty queue
 148   // to become the canonical one.
 149   _age.set(newAge);
 150   assert(dirty_size(localBot, _age.top()) != N - 1, "sanity");
 151   return false;
 152 }
 153 
 154 template<class E, MEMFLAGS F, unsigned int N> inline bool
 155 GenericTaskQueue<E, F, N>::pop_local(volatile E& t) {
 156   uint localBot = _bottom;
 157   // This value cannot be N-1.  That can only occur as a result of
 158   // the assignment to bottom in this method.  If it does, this method
 159   // resets the size to 0 before the next call (which is sequential,
 160   // since this is pop_local.)
 161   uint dirty_n_elems = dirty_size(localBot, _age.top());
 162   assert(dirty_n_elems != N - 1, "Shouldn't be possible...");
 163   if (dirty_n_elems == 0) return false;
 164   localBot = decrement_index(localBot);
 165   _bottom = localBot;
 166   // This is necessary to prevent any read below from being reordered
 167   // before the store just above.
 168   OrderAccess::fence();
 169   // g++ complains if the volatile result of the assignment is
 170   // unused, so we cast the volatile away.  We cannot cast directly
 171   // to void, because gcc treats that as not using the result of the
 172   // assignment.  However, casting to E& means that we trigger an
 173   // unused-value warning.  So, we cast the E& to void.
 174   (void) const_cast<E&>(t = _elems[localBot]);
 175   // This is a second read of "age"; the "size()" above is the first.
 176   // If there's still at least one element in the queue, based on the
 177   // "_bottom" and "age" we've read, then there can be no interference with
 178   // a "pop_global" operation, and we're done.
 179   idx_t tp = _age.top();    // XXX
 180   if (size(localBot, tp) > 0) {
 181     assert(dirty_size(localBot, tp) != N - 1, "sanity");
 182     TASKQUEUE_STATS_ONLY(stats.record_pop());
 183     return true;




 135   if (localBot == oldAge.top()) {
 136     // No competing pop_global has yet incremented "top"; we'll try to
 137     // install new_age, thus claiming the element.
 138     Age tempAge = _age.cmpxchg(newAge, oldAge);
 139     if (tempAge == oldAge) {
 140       // We win.
 141       assert(dirty_size(localBot, _age.top()) != N - 1, "sanity");
 142       TASKQUEUE_STATS_ONLY(stats.record_pop_slow());
 143       return true;
 144     }
 145   }
 146   // We lose; a completing pop_global gets the element.  But the queue is empty
 147   // and top is greater than bottom.  Fix this representation of the empty queue
 148   // to become the canonical one.
 149   _age.set(newAge);
 150   assert(dirty_size(localBot, _age.top()) != N - 1, "sanity");
 151   return false;
 152 }
 153 
 154 template<class E, MEMFLAGS F, unsigned int N> inline bool
 155 GenericTaskQueue<E, F, N>::pop_local(volatile E& t, uint threshold) {
 156   uint localBot = _bottom;
 157   // This value cannot be N-1.  That can only occur as a result of
 158   // the assignment to bottom in this method.  If it does, this method
 159   // resets the size to 0 before the next call (which is sequential,
 160   // since this is pop_local.)
 161   uint dirty_n_elems = dirty_size(localBot, _age.top());
 162   assert(dirty_n_elems != N - 1, "Shouldn't be possible...");
 163   if (dirty_n_elems <= threshold) return false;
 164   localBot = decrement_index(localBot);
 165   _bottom = localBot;
 166   // This is necessary to prevent any read below from being reordered
 167   // before the store just above.
 168   OrderAccess::fence();
 169   // g++ complains if the volatile result of the assignment is
 170   // unused, so we cast the volatile away.  We cannot cast directly
 171   // to void, because gcc treats that as not using the result of the
 172   // assignment.  However, casting to E& means that we trigger an
 173   // unused-value warning.  So, we cast the E& to void.
 174   (void) const_cast<E&>(t = _elems[localBot]);
 175   // This is a second read of "age"; the "size()" above is the first.
 176   // If there's still at least one element in the queue, based on the
 177   // "_bottom" and "age" we've read, then there can be no interference with
 178   // a "pop_global" operation, and we're done.
 179   idx_t tp = _age.top();    // XXX
 180   if (size(localBot, tp) > 0) {
 181     assert(dirty_size(localBot, tp) != N - 1, "sanity");
 182     TASKQUEUE_STATS_ONLY(stats.record_pop());
 183     return true;


< prev index next >