41 #include "utilities/count_trailing_zeros.hpp" |
41 #include "utilities/count_trailing_zeros.hpp" |
42 #include "utilities/debug.hpp" |
42 #include "utilities/debug.hpp" |
43 #include "utilities/globalDefinitions.hpp" |
43 #include "utilities/globalDefinitions.hpp" |
44 #include "utilities/macros.hpp" |
44 #include "utilities/macros.hpp" |
45 #include "utilities/ostream.hpp" |
45 #include "utilities/ostream.hpp" |
46 #include "utilities/spinYield.hpp" |
|
47 |
46 |
48 OopStorage::AllocationListEntry::AllocationListEntry() : _prev(NULL), _next(NULL) {} |
47 OopStorage::AllocationListEntry::AllocationListEntry() : _prev(NULL), _next(NULL) {} |
49 |
48 |
50 OopStorage::AllocationListEntry::~AllocationListEntry() { |
49 OopStorage::AllocationListEntry::~AllocationListEntry() { |
51 assert(_prev == NULL, "deleting attached block"); |
50 assert(_prev == NULL, "deleting attached block"); |
493 replace_active_array(new_array); |
492 replace_active_array(new_array); |
494 relinquish_block_array(old_array); |
493 relinquish_block_array(old_array); |
495 return true; |
494 return true; |
496 } |
495 } |
497 |
496 |
498 OopStorage::ProtectActive::ProtectActive() : _enter(0), _exit() {} |
|
499 |
|
500 // Begin read-side critical section. |
|
501 uint OopStorage::ProtectActive::read_enter() { |
|
502 return Atomic::add(2u, &_enter); |
|
503 } |
|
504 |
|
505 // End read-side critical section. |
|
506 void OopStorage::ProtectActive::read_exit(uint enter_value) { |
|
507 Atomic::add(2u, &_exit[enter_value & 1]); |
|
508 } |
|
509 |
|
510 // Wait until all readers that entered the critical section before |
|
511 // synchronization have exited that critical section. |
|
512 void OopStorage::ProtectActive::write_synchronize() { |
|
513 SpinYield spinner; |
|
514 // Determine old and new exit counters, based on bit0 of the |
|
515 // on-entry _enter counter. |
|
516 uint value = OrderAccess::load_acquire(&_enter); |
|
517 volatile uint* new_ptr = &_exit[(value + 1) & 1]; |
|
518 // Atomically change the in-use exit counter to the new counter, by |
|
519 // adding 1 to the _enter counter (flipping bit0 between 0 and 1) |
|
520 // and initializing the new exit counter to that enter value. Note: |
|
521 // The new exit counter is not being used by read operations until |
|
522 // this change succeeds. |
|
523 uint old; |
|
524 do { |
|
525 old = value; |
|
526 *new_ptr = ++value; |
|
527 value = Atomic::cmpxchg(value, &_enter, old); |
|
528 } while (old != value); |
|
529 // Readers that entered the critical section before we changed the |
|
530 // selected exit counter will use the old exit counter. Readers |
|
531 // entering after the change will use the new exit counter. Wait |
|
532 // for all the critical sections started before the change to |
|
533 // complete, e.g. for the value of old_ptr to catch up with old. |
|
534 volatile uint* old_ptr = &_exit[old & 1]; |
|
535 while (old != OrderAccess::load_acquire(old_ptr)) { |
|
536 spinner.wait(); |
|
537 } |
|
538 } |
|
539 |
|
540 // Make new_array the _active_array. Increments new_array's refcount |
497 // Make new_array the _active_array. Increments new_array's refcount |
541 // to account for the new reference. The assignment is atomic wrto |
498 // to account for the new reference. The assignment is atomic wrto |
542 // obtain_active_array; once this function returns, it is safe for the |
499 // obtain_active_array; once this function returns, it is safe for the |
543 // caller to relinquish the old array. |
500 // caller to relinquish the old array. |
544 void OopStorage::replace_active_array(ActiveArray* new_array) { |
501 void OopStorage::replace_active_array(ActiveArray* new_array) { |
546 // Update new_array refcount to account for the new reference. |
503 // Update new_array refcount to account for the new reference. |
547 new_array->increment_refcount(); |
504 new_array->increment_refcount(); |
548 // Install new_array, ensuring its initialization is complete first. |
505 // Install new_array, ensuring its initialization is complete first. |
549 OrderAccess::release_store(&_active_array, new_array); |
506 OrderAccess::release_store(&_active_array, new_array); |
550 // Wait for any readers that could read the old array from _active_array. |
507 // Wait for any readers that could read the old array from _active_array. |
551 _protect_active.write_synchronize(); |
508 // Can't use GlobalCounter here, because this is called from allocate(), |
|
509 // which may be called in the scope of a GlobalCounter critical section |
|
510 // when inserting a StringTable entry. |
|
511 _protect_active.synchronize(); |
552 // All obtain critical sections that could see the old array have |
512 // All obtain critical sections that could see the old array have |
553 // completed, having incremented the refcount of the old array. The |
513 // completed, having incremented the refcount of the old array. The |
554 // caller can now safely relinquish the old array. |
514 // caller can now safely relinquish the old array. |
555 } |
515 } |
556 |
516 |
558 // increment its refcount. This provides safe access to the array, |
518 // increment its refcount. This provides safe access to the array, |
559 // even if an allocate operation expands and replaces the value of |
519 // even if an allocate operation expands and replaces the value of |
560 // _active_array. The caller must relinquish the array when done |
520 // _active_array. The caller must relinquish the array when done |
561 // using it. |
521 // using it. |
562 OopStorage::ActiveArray* OopStorage::obtain_active_array() const { |
522 OopStorage::ActiveArray* OopStorage::obtain_active_array() const { |
563 uint enter_value = _protect_active.read_enter(); |
523 SingleWriterSynchronizer::CriticalSection cs(&_protect_active); |
564 ActiveArray* result = OrderAccess::load_acquire(&_active_array); |
524 ActiveArray* result = OrderAccess::load_acquire(&_active_array); |
565 result->increment_refcount(); |
525 result->increment_refcount(); |
566 _protect_active.read_exit(enter_value); |
|
567 return result; |
526 return result; |
568 } |
527 } |
569 |
528 |
570 // Decrement refcount of array and destroy if refcount is zero. |
529 // Decrement refcount of array and destroy if refcount is zero. |
571 void OopStorage::relinquish_block_array(ActiveArray* array) const { |
530 void OopStorage::relinquish_block_array(ActiveArray* array) const { |