972 } |
972 } |
973 |
973 |
974 JvmtiDeferredEventQueue::QueueNode* JvmtiDeferredEventQueue::_queue_tail = NULL; |
974 JvmtiDeferredEventQueue::QueueNode* JvmtiDeferredEventQueue::_queue_tail = NULL; |
975 JvmtiDeferredEventQueue::QueueNode* JvmtiDeferredEventQueue::_queue_head = NULL; |
975 JvmtiDeferredEventQueue::QueueNode* JvmtiDeferredEventQueue::_queue_head = NULL; |
976 |
976 |
977 volatile JvmtiDeferredEventQueue::QueueNode* |
|
978 JvmtiDeferredEventQueue::_pending_list = NULL; |
|
979 |
|
980 bool JvmtiDeferredEventQueue::has_events() { |
977 bool JvmtiDeferredEventQueue::has_events() { |
981 assert(Service_lock->owned_by_self(), "Must own Service_lock"); |
978 assert(Service_lock->owned_by_self(), "Must own Service_lock"); |
982 return _queue_head != NULL || _pending_list != NULL; |
979 return _queue_head != NULL; |
983 } |
980 } |
984 |
981 |
985 void JvmtiDeferredEventQueue::enqueue(const JvmtiDeferredEvent& event) { |
982 void JvmtiDeferredEventQueue::enqueue(const JvmtiDeferredEvent& event) { |
986 assert(Service_lock->owned_by_self(), "Must own Service_lock"); |
983 assert(Service_lock->owned_by_self(), "Must own Service_lock"); |
987 |
|
988 process_pending_events(); |
|
989 |
984 |
990 // Events get added to the end of the queue (and are pulled off the front). |
985 // Events get added to the end of the queue (and are pulled off the front). |
991 QueueNode* node = new QueueNode(event); |
986 QueueNode* node = new QueueNode(event); |
992 if (_queue_tail == NULL) { |
987 if (_queue_tail == NULL) { |
993 _queue_tail = _queue_head = node; |
988 _queue_tail = _queue_head = node; |
1003 } |
998 } |
1004 |
999 |
1005 JvmtiDeferredEvent JvmtiDeferredEventQueue::dequeue() { |
1000 JvmtiDeferredEvent JvmtiDeferredEventQueue::dequeue() { |
1006 assert(Service_lock->owned_by_self(), "Must own Service_lock"); |
1001 assert(Service_lock->owned_by_self(), "Must own Service_lock"); |
1007 |
1002 |
1008 process_pending_events(); |
|
1009 |
|
1010 assert(_queue_head != NULL, "Nothing to dequeue"); |
1003 assert(_queue_head != NULL, "Nothing to dequeue"); |
1011 |
1004 |
1012 if (_queue_head == NULL) { |
1005 if (_queue_head == NULL) { |
1013 // Just in case this happens in product; it shouldn't but let's not crash |
1006 // Just in case this happens in product; it shouldn't but let's not crash |
1014 return JvmtiDeferredEvent(); |
1007 return JvmtiDeferredEvent(); |
1025 |
1018 |
1026 JvmtiDeferredEvent event = node->event(); |
1019 JvmtiDeferredEvent event = node->event(); |
1027 delete node; |
1020 delete node; |
1028 return event; |
1021 return event; |
1029 } |
1022 } |
1030 |
|
1031 void JvmtiDeferredEventQueue::add_pending_event( |
|
1032 const JvmtiDeferredEvent& event) { |
|
1033 |
|
1034 QueueNode* node = new QueueNode(event); |
|
1035 |
|
1036 bool success = false; |
|
1037 QueueNode* prev_value = (QueueNode*)_pending_list; |
|
1038 do { |
|
1039 node->set_next(prev_value); |
|
1040 prev_value = (QueueNode*)Atomic::cmpxchg_ptr( |
|
1041 (void*)node, (volatile void*)&_pending_list, (void*)node->next()); |
|
1042 } while (prev_value != node->next()); |
|
1043 } |
|
1044 |
|
1045 // This method transfers any events that were added by someone NOT holding |
|
1046 // the lock into the mainline queue. |
|
1047 void JvmtiDeferredEventQueue::process_pending_events() { |
|
1048 assert(Service_lock->owned_by_self(), "Must own Service_lock"); |
|
1049 |
|
1050 if (_pending_list != NULL) { |
|
1051 QueueNode* head = |
|
1052 (QueueNode*)Atomic::xchg_ptr(NULL, (volatile void*)&_pending_list); |
|
1053 |
|
1054 assert((_queue_head == NULL) == (_queue_tail == NULL), |
|
1055 "Inconsistent queue markers"); |
|
1056 |
|
1057 if (head != NULL) { |
|
1058 // Since we've treated the pending list as a stack (with newer |
|
1059 // events at the beginning), we need to join the bottom of the stack |
|
1060 // with the 'tail' of the queue in order to get the events in the |
|
1061 // right order. We do this by reversing the pending list and appending |
|
1062 // it to the queue. |
|
1063 |
|
1064 QueueNode* new_tail = head; |
|
1065 QueueNode* new_head = NULL; |
|
1066 |
|
1067 // This reverses the list |
|
1068 QueueNode* prev = new_tail; |
|
1069 QueueNode* node = new_tail->next(); |
|
1070 new_tail->set_next(NULL); |
|
1071 while (node != NULL) { |
|
1072 QueueNode* next = node->next(); |
|
1073 node->set_next(prev); |
|
1074 prev = node; |
|
1075 node = next; |
|
1076 } |
|
1077 new_head = prev; |
|
1078 |
|
1079 // Now append the new list to the queue |
|
1080 if (_queue_tail != NULL) { |
|
1081 _queue_tail->set_next(new_head); |
|
1082 } else { // _queue_head == NULL |
|
1083 _queue_head = new_head; |
|
1084 } |
|
1085 _queue_tail = new_tail; |
|
1086 } |
|
1087 } |
|
1088 } |
|