109 class TaskQueueSuper: public CHeapObj<F> { |
109 class TaskQueueSuper: public CHeapObj<F> { |
110 protected: |
110 protected: |
111 // Internal type for indexing the queue; also used for the tag. |
111 // Internal type for indexing the queue; also used for the tag. |
112 typedef NOT_LP64(uint16_t) LP64_ONLY(uint32_t) idx_t; |
112 typedef NOT_LP64(uint16_t) LP64_ONLY(uint32_t) idx_t; |
113 |
113 |
114 #ifdef MIPS64 |
114 #ifdef MIPS |
115 private: |
115 private: |
116 #endif |
116 #endif |
117 // The first free element after the last one pushed (mod N). |
117 // The first free element after the last one pushed (mod N). |
118 volatile uint _bottom; |
118 volatile uint _bottom; |
119 |
119 |
120 #ifdef MIPS64 |
120 #ifdef MIPS |
121 protected: |
121 protected: |
122 inline uint get_bottom() const { |
122 inline uint get_bottom() const { |
123 return OrderAccess::load_acquire((volatile juint*)&_bottom); |
123 return OrderAccess::load_acquire((volatile juint*)&_bottom); |
124 } |
124 } |
125 |
125 |
134 public: |
134 public: |
135 Age(size_t data = 0) { _data = data; } |
135 Age(size_t data = 0) { _data = data; } |
136 Age(const Age& age) { _data = age._data; } |
136 Age(const Age& age) { _data = age._data; } |
137 Age(idx_t top, idx_t tag) { _fields._top = top; _fields._tag = tag; } |
137 Age(idx_t top, idx_t tag) { _fields._top = top; _fields._tag = tag; } |
138 |
138 |
139 #ifndef MIPS64 |
139 #ifndef MIPS |
140 Age get() const volatile { return _data; } |
140 Age get() const volatile { return _data; } |
141 void set(Age age) volatile { _data = age._data; } |
141 void set(Age age) volatile { _data = age._data; } |
142 |
142 |
143 idx_t top() const volatile { return _fields._top; } |
143 idx_t top() const volatile { return _fields._top; } |
144 idx_t tag() const volatile { return _fields._tag; } |
144 idx_t tag() const volatile { return _fields._tag; } |
229 |
229 |
230 // Return an estimate of the number of elements in the queue. |
230 // Return an estimate of the number of elements in the queue. |
231 // The "careful" version admits the possibility of pop_local/pop_global |
231 // The "careful" version admits the possibility of pop_local/pop_global |
232 // races. |
232 // races. |
233 uint size() const { |
233 uint size() const { |
234 #ifdef MIPS64 |
234 #ifdef MIPS |
235 return size(get_bottom(), _age.top()); |
235 return size(get_bottom(), _age.top()); |
236 #else |
236 #else |
237 return size(_bottom, _age.top()); |
237 return size(_bottom, _age.top()); |
238 #endif |
238 #endif |
239 } |
239 } |
240 |
240 |
241 uint dirty_size() const { |
241 uint dirty_size() const { |
242 #ifdef MIPS64 |
242 #ifdef MIPS |
243 return dirty_size(get_bottom(), _age.top()); |
243 return dirty_size(get_bottom(), _age.top()); |
244 #else |
244 #else |
245 return dirty_size(_bottom, _age.top()); |
245 return dirty_size(_bottom, _age.top()); |
246 #endif |
246 #endif |
247 } |
247 } |
248 |
248 |
249 void set_empty() { |
249 void set_empty() { |
250 #ifdef MIPS64 |
250 #ifdef MIPS |
251 set_bottom(0); |
251 set_bottom(0); |
252 #else |
252 #else |
253 _bottom = 0; |
253 _bottom = 0; |
254 #endif |
254 #endif |
255 _age.set(0); |
255 _age.set(0); |
301 ArrayAllocator<E, F> _array_allocator; |
301 ArrayAllocator<E, F> _array_allocator; |
302 protected: |
302 protected: |
303 typedef typename TaskQueueSuper<N, F>::Age Age; |
303 typedef typename TaskQueueSuper<N, F>::Age Age; |
304 typedef typename TaskQueueSuper<N, F>::idx_t idx_t; |
304 typedef typename TaskQueueSuper<N, F>::idx_t idx_t; |
305 |
305 |
306 #ifndef MIPS64 |
306 #ifndef MIPS |
307 using TaskQueueSuper<N, F>::_bottom; |
307 using TaskQueueSuper<N, F>::_bottom; |
308 #endif |
308 #endif |
309 using TaskQueueSuper<N, F>::_age; |
309 using TaskQueueSuper<N, F>::_age; |
310 using TaskQueueSuper<N, F>::increment_index; |
310 using TaskQueueSuper<N, F>::increment_index; |
311 using TaskQueueSuper<N, F>::decrement_index; |
311 using TaskQueueSuper<N, F>::decrement_index; |
367 |
367 |
368 template<class E, MEMFLAGS F, unsigned int N> |
368 template<class E, MEMFLAGS F, unsigned int N> |
369 void GenericTaskQueue<E, F, N>::oops_do(OopClosure* f) { |
369 void GenericTaskQueue<E, F, N>::oops_do(OopClosure* f) { |
370 // tty->print_cr("START OopTaskQueue::oops_do"); |
370 // tty->print_cr("START OopTaskQueue::oops_do"); |
371 uint iters = size(); |
371 uint iters = size(); |
372 #ifdef MIPS64 |
372 #ifdef MIPS |
373 uint index = this->get_bottom(); |
373 uint index = this->get_bottom(); |
374 #else |
374 #else |
375 uint index = _bottom; |
375 uint index = _bottom; |
376 #endif |
376 #endif |
377 for (uint i = 0; i < iters; ++i) { |
377 for (uint i = 0; i < iters; ++i) { |
388 |
388 |
389 template<class E, MEMFLAGS F, unsigned int N> |
389 template<class E, MEMFLAGS F, unsigned int N> |
390 bool GenericTaskQueue<E, F, N>::push_slow(E t, uint dirty_n_elems) { |
390 bool GenericTaskQueue<E, F, N>::push_slow(E t, uint dirty_n_elems) { |
391 if (dirty_n_elems == N - 1) { |
391 if (dirty_n_elems == N - 1) { |
392 // Actually means 0, so do the push. |
392 // Actually means 0, so do the push. |
393 #ifdef MIPS64 |
393 #ifdef MIPS |
394 uint localBot = this->get_bottom(); |
394 uint localBot = this->get_bottom(); |
395 #else |
395 #else |
396 uint localBot = _bottom; |
396 uint localBot = _bottom; |
397 #endif |
397 #endif |
398 // g++ complains if the volatile result of the assignment is |
398 // g++ complains if the volatile result of the assignment is |
399 // unused, so we cast the volatile away. We cannot cast directly |
399 // unused, so we cast the volatile away. We cannot cast directly |
400 // to void, because gcc treats that as not using the result of the |
400 // to void, because gcc treats that as not using the result of the |
401 // assignment. However, casting to E& means that we trigger an |
401 // assignment. However, casting to E& means that we trigger an |
402 // unused-value warning. So, we cast the E& to void. |
402 // unused-value warning. So, we cast the E& to void. |
403 (void)const_cast<E&>(_elems[localBot] = t); |
403 (void)const_cast<E&>(_elems[localBot] = t); |
404 #ifdef MIPS64 |
404 #ifdef MIPS |
405 this->set_bottom(increment_index(localBot)); |
405 this->set_bottom(increment_index(localBot)); |
406 #else |
406 #else |
407 OrderAccess::release_store(&_bottom, increment_index(localBot)); |
407 OrderAccess::release_store(&_bottom, increment_index(localBot)); |
408 #endif |
408 #endif |
409 TASKQUEUE_STATS_ONLY(stats.record_push()); |
409 TASKQUEUE_STATS_ONLY(stats.record_push()); |
458 // to guarantee that bottom is not older than age, |
458 // to guarantee that bottom is not older than age, |
459 // which is crucial for the correctness of the algorithm. |
459 // which is crucial for the correctness of the algorithm. |
460 #if !(defined SPARC || defined IA32 || defined AMD64) |
460 #if !(defined SPARC || defined IA32 || defined AMD64) |
461 OrderAccess::fence(); |
461 OrderAccess::fence(); |
462 #endif |
462 #endif |
463 #ifdef MIPS64 |
463 #ifdef MIPS |
464 uint localBot = this->get_bottom(); |
464 uint localBot = this->get_bottom(); |
465 #else |
465 #else |
466 uint localBot = OrderAccess::load_acquire((volatile juint*)&_bottom); |
466 uint localBot = OrderAccess::load_acquire((volatile juint*)&_bottom); |
467 #endif |
467 #endif |
468 uint n_elems = size(localBot, oldAge.top()); |
468 uint n_elems = size(localBot, oldAge.top()); |
717 #endif |
717 #endif |
718 }; |
718 }; |
719 |
719 |
720 template<class E, MEMFLAGS F, unsigned int N> inline bool |
720 template<class E, MEMFLAGS F, unsigned int N> inline bool |
721 GenericTaskQueue<E, F, N>::push(E t) { |
721 GenericTaskQueue<E, F, N>::push(E t) { |
722 #ifdef MIPS64 |
722 #ifdef MIPS |
723 uint localBot = this->get_bottom(); |
723 uint localBot = this->get_bottom(); |
724 #else |
724 #else |
725 uint localBot = _bottom; |
725 uint localBot = _bottom; |
726 #endif |
726 #endif |
727 assert(localBot < N, "_bottom out of range."); |
727 assert(localBot < N, "_bottom out of range."); |
733 // unused, so we cast the volatile away. We cannot cast directly |
733 // unused, so we cast the volatile away. We cannot cast directly |
734 // to void, because gcc treats that as not using the result of the |
734 // to void, because gcc treats that as not using the result of the |
735 // assignment. However, casting to E& means that we trigger an |
735 // assignment. However, casting to E& means that we trigger an |
736 // unused-value warning. So, we cast the E& to void. |
736 // unused-value warning. So, we cast the E& to void. |
737 (void) const_cast<E&>(_elems[localBot] = t); |
737 (void) const_cast<E&>(_elems[localBot] = t); |
738 #ifdef MIPS64 |
738 #ifdef MIPS |
739 this->set_bottom(increment_index(localBot)); |
739 this->set_bottom(increment_index(localBot)); |
740 #else |
740 #else |
741 OrderAccess::release_store(&_bottom, increment_index(localBot)); |
741 OrderAccess::release_store(&_bottom, increment_index(localBot)); |
742 #endif |
742 #endif |
743 TASKQUEUE_STATS_ONLY(stats.record_push()); |
743 TASKQUEUE_STATS_ONLY(stats.record_push()); |
747 } |
747 } |
748 } |
748 } |
749 |
749 |
750 template<class E, MEMFLAGS F, unsigned int N> inline bool |
750 template<class E, MEMFLAGS F, unsigned int N> inline bool |
751 GenericTaskQueue<E, F, N>::pop_local(volatile E& t) { |
751 GenericTaskQueue<E, F, N>::pop_local(volatile E& t) { |
752 #ifdef MIPS64 |
752 #ifdef MIPS |
753 uint localBot = this->get_bottom(); |
753 uint localBot = this->get_bottom(); |
754 #else |
754 #else |
755 uint localBot = _bottom; |
755 uint localBot = _bottom; |
756 #endif |
756 #endif |
757 // This value cannot be N-1. That can only occur as a result of |
757 // This value cannot be N-1. That can only occur as a result of |
760 // since this is pop_local.) |
760 // since this is pop_local.) |
761 uint dirty_n_elems = dirty_size(localBot, _age.top()); |
761 uint dirty_n_elems = dirty_size(localBot, _age.top()); |
762 assert(dirty_n_elems != N - 1, "Shouldn't be possible..."); |
762 assert(dirty_n_elems != N - 1, "Shouldn't be possible..."); |
763 if (dirty_n_elems == 0) return false; |
763 if (dirty_n_elems == 0) return false; |
764 localBot = decrement_index(localBot); |
764 localBot = decrement_index(localBot); |
765 #ifdef MIPS64 |
765 #ifdef MIPS |
766 this->set_bottom(localBot); |
766 this->set_bottom(localBot); |
767 #else |
767 #else |
768 _bottom = localBot; |
768 _bottom = localBot; |
769 #endif |
769 #endif |
770 // This is necessary to prevent any read below from being reordered |
770 // This is necessary to prevent any read below from being reordered |