8164563: Test nsk/jvmti/CompiledMethodUnload/compmethunload001 keeps reporting: PRODUCT BUG: class was not unloaded in 5
Removed _pending_list Reviewed-by: dholmes, sspitsyn, dcubed, coleenp
This commit is contained in:
parent
7b8b238986
commit
7aabb799f6
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -1459,14 +1459,8 @@ void nmethod::post_compiled_method_unload() {
|
||||
JvmtiDeferredEvent event =
|
||||
JvmtiDeferredEvent::compiled_method_unload_event(this,
|
||||
_jmethod_id, insts_begin());
|
||||
if (SafepointSynchronize::is_at_safepoint()) {
|
||||
// Don't want to take the queueing lock. Add it as pending and
|
||||
// it will get enqueued later.
|
||||
JvmtiDeferredEventQueue::add_pending_event(event);
|
||||
} else {
|
||||
MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
|
||||
JvmtiDeferredEventQueue::enqueue(event);
|
||||
}
|
||||
MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
|
||||
JvmtiDeferredEventQueue::enqueue(event);
|
||||
}
|
||||
|
||||
// The JVMTI CompiledMethodUnload event can be enabled or disabled at
|
||||
|
@ -974,19 +974,14 @@ void JvmtiDeferredEvent::post() {
|
||||
JvmtiDeferredEventQueue::QueueNode* JvmtiDeferredEventQueue::_queue_tail = NULL;
|
||||
JvmtiDeferredEventQueue::QueueNode* JvmtiDeferredEventQueue::_queue_head = NULL;
|
||||
|
||||
volatile JvmtiDeferredEventQueue::QueueNode*
|
||||
JvmtiDeferredEventQueue::_pending_list = NULL;
|
||||
|
||||
bool JvmtiDeferredEventQueue::has_events() {
|
||||
assert(Service_lock->owned_by_self(), "Must own Service_lock");
|
||||
return _queue_head != NULL || _pending_list != NULL;
|
||||
return _queue_head != NULL;
|
||||
}
|
||||
|
||||
void JvmtiDeferredEventQueue::enqueue(const JvmtiDeferredEvent& event) {
|
||||
assert(Service_lock->owned_by_self(), "Must own Service_lock");
|
||||
|
||||
process_pending_events();
|
||||
|
||||
// Events get added to the end of the queue (and are pulled off the front).
|
||||
QueueNode* node = new QueueNode(event);
|
||||
if (_queue_tail == NULL) {
|
||||
@ -1005,8 +1000,6 @@ void JvmtiDeferredEventQueue::enqueue(const JvmtiDeferredEvent& event) {
|
||||
JvmtiDeferredEvent JvmtiDeferredEventQueue::dequeue() {
|
||||
assert(Service_lock->owned_by_self(), "Must own Service_lock");
|
||||
|
||||
process_pending_events();
|
||||
|
||||
assert(_queue_head != NULL, "Nothing to dequeue");
|
||||
|
||||
if (_queue_head == NULL) {
|
||||
@ -1027,62 +1020,3 @@ JvmtiDeferredEvent JvmtiDeferredEventQueue::dequeue() {
|
||||
delete node;
|
||||
return event;
|
||||
}
|
||||
|
||||
void JvmtiDeferredEventQueue::add_pending_event(
|
||||
const JvmtiDeferredEvent& event) {
|
||||
|
||||
QueueNode* node = new QueueNode(event);
|
||||
|
||||
bool success = false;
|
||||
QueueNode* prev_value = (QueueNode*)_pending_list;
|
||||
do {
|
||||
node->set_next(prev_value);
|
||||
prev_value = (QueueNode*)Atomic::cmpxchg_ptr(
|
||||
(void*)node, (volatile void*)&_pending_list, (void*)node->next());
|
||||
} while (prev_value != node->next());
|
||||
}
|
||||
|
||||
// This method transfers any events that were added by someone NOT holding
|
||||
// the lock into the mainline queue.
|
||||
void JvmtiDeferredEventQueue::process_pending_events() {
|
||||
assert(Service_lock->owned_by_self(), "Must own Service_lock");
|
||||
|
||||
if (_pending_list != NULL) {
|
||||
QueueNode* head =
|
||||
(QueueNode*)Atomic::xchg_ptr(NULL, (volatile void*)&_pending_list);
|
||||
|
||||
assert((_queue_head == NULL) == (_queue_tail == NULL),
|
||||
"Inconsistent queue markers");
|
||||
|
||||
if (head != NULL) {
|
||||
// Since we've treated the pending list as a stack (with newer
|
||||
// events at the beginning), we need to join the bottom of the stack
|
||||
// with the 'tail' of the queue in order to get the events in the
|
||||
// right order. We do this by reversing the pending list and appending
|
||||
// it to the queue.
|
||||
|
||||
QueueNode* new_tail = head;
|
||||
QueueNode* new_head = NULL;
|
||||
|
||||
// This reverses the list
|
||||
QueueNode* prev = new_tail;
|
||||
QueueNode* node = new_tail->next();
|
||||
new_tail->set_next(NULL);
|
||||
while (node != NULL) {
|
||||
QueueNode* next = node->next();
|
||||
node->set_next(prev);
|
||||
prev = node;
|
||||
node = next;
|
||||
}
|
||||
new_head = prev;
|
||||
|
||||
// Now append the new list to the queue
|
||||
if (_queue_tail != NULL) {
|
||||
_queue_tail->set_next(new_head);
|
||||
} else { // _queue_head == NULL
|
||||
_queue_head = new_head;
|
||||
}
|
||||
_queue_tail = new_tail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -497,7 +497,7 @@ class JvmtiDeferredEvent VALUE_OBJ_CLASS_SPEC {
|
||||
/**
|
||||
* Events enqueued on this queue wake up the Service thread which dequeues
|
||||
* and posts the events. The Service_lock is required to be held
|
||||
* when operating on the queue (except for the "pending" events).
|
||||
* when operating on the queue.
|
||||
*/
|
||||
class JvmtiDeferredEventQueue : AllStatic {
|
||||
friend class JvmtiDeferredEvent;
|
||||
@ -519,24 +519,12 @@ class JvmtiDeferredEventQueue : AllStatic {
|
||||
|
||||
static QueueNode* _queue_head; // Hold Service_lock to access
|
||||
static QueueNode* _queue_tail; // Hold Service_lock to access
|
||||
static volatile QueueNode* _pending_list; // Uses CAS for read/update
|
||||
|
||||
// Transfers events from the _pending_list to the _queue.
|
||||
static void process_pending_events() NOT_JVMTI_RETURN;
|
||||
|
||||
public:
|
||||
// Must be holding Service_lock when calling these
|
||||
static bool has_events() NOT_JVMTI_RETURN_(false);
|
||||
static void enqueue(const JvmtiDeferredEvent& event) NOT_JVMTI_RETURN;
|
||||
static JvmtiDeferredEvent dequeue() NOT_JVMTI_RETURN_(JvmtiDeferredEvent());
|
||||
|
||||
// Used to enqueue events without using a lock, for times (such as during
|
||||
// safepoint) when we can't or don't want to lock the Service_lock.
|
||||
//
|
||||
// Events will be held off to the side until there's a call to
|
||||
// dequeue(), enqueue(), or process_pending_events() (all of which require
|
||||
// the holding of the Service_lock), and will be enqueued at that time.
|
||||
static void add_pending_event(const JvmtiDeferredEvent&) NOT_JVMTI_RETURN;
|
||||
};
|
||||
|
||||
// Utility macro that checks for NULL pointers:
|
||||
|
Loading…
x
Reference in New Issue
Block a user