mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 23:34:52 +02:00
8164207: Checking missing load-acquire in relation to _pd_set in dictionary.cpp
Use load_acquire for accessing DictionaryEntry::_pd_set since it's accessed outside the SystemDictionary_lock Reviewed-by: zgu, twisti, dholmes, adinn
This commit is contained in:
parent
f1ff1ca94b
commit
de3cc93ca6
3 changed files with 21 additions and 15 deletions
|
@ -85,6 +85,7 @@ DictionaryEntry* Dictionary::new_entry(unsigned int hash, InstanceKlass* klass)
|
||||||
|
|
||||||
void Dictionary::free_entry(DictionaryEntry* entry) {
|
void Dictionary::free_entry(DictionaryEntry* entry) {
|
||||||
// avoid recursion when deleting linked list
|
// avoid recursion when deleting linked list
|
||||||
|
// pd_set is accessed during a safepoint.
|
||||||
while (entry->pd_set() != NULL) {
|
while (entry->pd_set() != NULL) {
|
||||||
ProtectionDomainEntry* to_delete = entry->pd_set();
|
ProtectionDomainEntry* to_delete = entry->pd_set();
|
||||||
entry->set_pd_set(to_delete->next());
|
entry->set_pd_set(to_delete->next());
|
||||||
|
@ -101,7 +102,7 @@ bool DictionaryEntry::contains_protection_domain(oop protection_domain) const {
|
||||||
if (protection_domain == instance_klass()->protection_domain()) {
|
if (protection_domain == instance_klass()->protection_domain()) {
|
||||||
// Ensure this doesn't show up in the pd_set (invariant)
|
// Ensure this doesn't show up in the pd_set (invariant)
|
||||||
bool in_pd_set = false;
|
bool in_pd_set = false;
|
||||||
for (ProtectionDomainEntry* current = _pd_set;
|
for (ProtectionDomainEntry* current = pd_set_acquire();
|
||||||
current != NULL;
|
current != NULL;
|
||||||
current = current->next()) {
|
current = current->next()) {
|
||||||
if (current->protection_domain() == protection_domain) {
|
if (current->protection_domain() == protection_domain) {
|
||||||
|
@ -121,7 +122,7 @@ bool DictionaryEntry::contains_protection_domain(oop protection_domain) const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ProtectionDomainEntry* current = _pd_set;
|
for (ProtectionDomainEntry* current = pd_set_acquire();
|
||||||
current != NULL;
|
current != NULL;
|
||||||
current = current->next()) {
|
current = current->next()) {
|
||||||
if (current->protection_domain() == protection_domain) return true;
|
if (current->protection_domain() == protection_domain) return true;
|
||||||
|
@ -135,12 +136,12 @@ void DictionaryEntry::add_protection_domain(Dictionary* dict, Handle protection_
|
||||||
if (!contains_protection_domain(protection_domain())) {
|
if (!contains_protection_domain(protection_domain())) {
|
||||||
ProtectionDomainCacheEntry* entry = SystemDictionary::cache_get(protection_domain);
|
ProtectionDomainCacheEntry* entry = SystemDictionary::cache_get(protection_domain);
|
||||||
ProtectionDomainEntry* new_head =
|
ProtectionDomainEntry* new_head =
|
||||||
new ProtectionDomainEntry(entry, _pd_set);
|
new ProtectionDomainEntry(entry, pd_set());
|
||||||
// Warning: Preserve store ordering. The SystemDictionary is read
|
// Warning: Preserve store ordering. The SystemDictionary is read
|
||||||
// without locks. The new ProtectionDomainEntry must be
|
// without locks. The new ProtectionDomainEntry must be
|
||||||
// complete before other threads can be allowed to see it
|
// complete before other threads can be allowed to see it
|
||||||
// via a store to _pd_set.
|
// via a store to _pd_set.
|
||||||
OrderAccess::release_store_ptr(&_pd_set, new_head);
|
release_set_pd_set(new_head);
|
||||||
}
|
}
|
||||||
LogTarget(Trace, protectiondomain) lt;
|
LogTarget(Trace, protectiondomain) lt;
|
||||||
if (lt.is_enabled()) {
|
if (lt.is_enabled()) {
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "oops/instanceKlass.hpp"
|
#include "oops/instanceKlass.hpp"
|
||||||
#include "oops/oop.hpp"
|
#include "oops/oop.hpp"
|
||||||
|
#include "runtime/orderAccess.hpp"
|
||||||
#include "utilities/hashtable.hpp"
|
#include "utilities/hashtable.hpp"
|
||||||
#include "utilities/ostream.hpp"
|
#include "utilities/ostream.hpp"
|
||||||
|
|
||||||
|
@ -134,7 +135,7 @@ class DictionaryEntry : public HashtableEntry<InstanceKlass*, mtClass> {
|
||||||
// It is essentially a cache to avoid repeated Java up-calls to
|
// It is essentially a cache to avoid repeated Java up-calls to
|
||||||
// ClassLoader.checkPackageAccess().
|
// ClassLoader.checkPackageAccess().
|
||||||
//
|
//
|
||||||
ProtectionDomainEntry* _pd_set;
|
ProtectionDomainEntry* volatile _pd_set;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Tells whether a protection is in the approved set.
|
// Tells whether a protection is in the approved set.
|
||||||
|
@ -154,7 +155,14 @@ class DictionaryEntry : public HashtableEntry<InstanceKlass*, mtClass> {
|
||||||
}
|
}
|
||||||
|
|
||||||
ProtectionDomainEntry* pd_set() const { return _pd_set; }
|
ProtectionDomainEntry* pd_set() const { return _pd_set; }
|
||||||
void set_pd_set(ProtectionDomainEntry* pd_set) { _pd_set = pd_set; }
|
void set_pd_set(ProtectionDomainEntry* new_head) { _pd_set = new_head; }
|
||||||
|
|
||||||
|
ProtectionDomainEntry* pd_set_acquire() const {
|
||||||
|
return (ProtectionDomainEntry*)OrderAccess::load_ptr_acquire(&_pd_set);
|
||||||
|
}
|
||||||
|
void release_set_pd_set(ProtectionDomainEntry* new_head) {
|
||||||
|
OrderAccess::release_store_ptr(&_pd_set, new_head);
|
||||||
|
}
|
||||||
|
|
||||||
// Tells whether the initiating class' protection domain can access the klass in this entry
|
// Tells whether the initiating class' protection domain can access the klass in this entry
|
||||||
bool is_valid_protection_domain(Handle protection_domain) {
|
bool is_valid_protection_domain(Handle protection_domain) {
|
||||||
|
@ -167,7 +175,7 @@ class DictionaryEntry : public HashtableEntry<InstanceKlass*, mtClass> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void verify_protection_domain_set() {
|
void verify_protection_domain_set() {
|
||||||
for (ProtectionDomainEntry* current = _pd_set;
|
for (ProtectionDomainEntry* current = pd_set(); // accessed at a safepoint
|
||||||
current != NULL;
|
current != NULL;
|
||||||
current = current->_next) {
|
current = current->_next) {
|
||||||
current->_pd_cache->protection_domain()->verify();
|
current->_pd_cache->protection_domain()->verify();
|
||||||
|
@ -181,7 +189,7 @@ class DictionaryEntry : public HashtableEntry<InstanceKlass*, mtClass> {
|
||||||
|
|
||||||
void print_count(outputStream *st) {
|
void print_count(outputStream *st) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (ProtectionDomainEntry* current = _pd_set;
|
for (ProtectionDomainEntry* current = pd_set(); // accessed inside SD lock
|
||||||
current != NULL;
|
current != NULL;
|
||||||
current = current->_next) {
|
current = current->_next) {
|
||||||
count++;
|
count++;
|
||||||
|
|
|
@ -910,13 +910,10 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
||||||
if (protection_domain() == NULL) return k;
|
if (protection_domain() == NULL) return k;
|
||||||
|
|
||||||
// Check the protection domain has the right access
|
// Check the protection domain has the right access
|
||||||
{
|
|
||||||
MutexLocker mu(SystemDictionary_lock, THREAD);
|
|
||||||
if (dictionary->is_valid_protection_domain(d_index, d_hash, name,
|
if (dictionary->is_valid_protection_domain(d_index, d_hash, name,
|
||||||
protection_domain)) {
|
protection_domain)) {
|
||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Verify protection domain. If it fails an exception is thrown
|
// Verify protection domain. If it fails an exception is thrown
|
||||||
validate_protection_domain(k, class_loader, protection_domain, CHECK_NULL);
|
validate_protection_domain(k, class_loader, protection_domain, CHECK_NULL);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue