comparison src/share/vm/prims/jvmtiImpl.cpp @ 2301:f91db74a6810

7017640: Fix for 6766644 deadlocks on some NSK tests when running with -Xcomp Summary: Dynamic-code generated events should be deferred and processed by service thread Reviewed-by: dsamersoff, dcubed
author kamg
date Sat, 26 Feb 2011 13:33:23 -0500
parents bf8517f4e4d0
children 46a56fac55c7
comparison
equal deleted inserted replaced
2265:162b62460264 2301:f91db74a6810
916 #ifndef KERNEL 916 #ifndef KERNEL
917 917
918 JvmtiDeferredEvent JvmtiDeferredEvent::compiled_method_load_event( 918 JvmtiDeferredEvent JvmtiDeferredEvent::compiled_method_load_event(
919 nmethod* nm) { 919 nmethod* nm) {
920 JvmtiDeferredEvent event = JvmtiDeferredEvent(TYPE_COMPILED_METHOD_LOAD); 920 JvmtiDeferredEvent event = JvmtiDeferredEvent(TYPE_COMPILED_METHOD_LOAD);
921 event.set_compiled_method_load(nm); 921 event._event_data.compiled_method_load = nm;
922 nmethodLocker::lock_nmethod(nm); // will be unlocked when posted 922 nmethodLocker::lock_nmethod(nm); // will be unlocked when posted
923 return event; 923 return event;
924 } 924 }
925 925
926 JvmtiDeferredEvent JvmtiDeferredEvent::compiled_method_unload_event( 926 JvmtiDeferredEvent JvmtiDeferredEvent::compiled_method_unload_event(
927 jmethodID id, const void* code) { 927 jmethodID id, const void* code) {
928 JvmtiDeferredEvent event = JvmtiDeferredEvent(TYPE_COMPILED_METHOD_UNLOAD); 928 JvmtiDeferredEvent event = JvmtiDeferredEvent(TYPE_COMPILED_METHOD_UNLOAD);
929 event.set_compiled_method_unload(id, code); 929 event._event_data.compiled_method_unload.method_id = id;
930 event._event_data.compiled_method_unload.code_begin = code;
930 return event; 931 return event;
931 } 932 }
933 JvmtiDeferredEvent JvmtiDeferredEvent::dynamic_code_generated_event(
934 const char* name, const void* code_begin, const void* code_end) {
935 JvmtiDeferredEvent event = JvmtiDeferredEvent(TYPE_DYNAMIC_CODE_GENERATED);
936 event._event_data.dynamic_code_generated.name = name;
937 event._event_data.dynamic_code_generated.code_begin = code_begin;
938 event._event_data.dynamic_code_generated.code_end = code_end;
939 return event;
940 }
932 941
933 void JvmtiDeferredEvent::post() { 942 void JvmtiDeferredEvent::post() {
943 assert(ServiceThread::is_service_thread(Thread::current()),
944 "Service thread must post enqueued events");
934 switch(_type) { 945 switch(_type) {
935 case TYPE_COMPILED_METHOD_LOAD: 946 case TYPE_COMPILED_METHOD_LOAD: {
936 JvmtiExport::post_compiled_method_load(compiled_method_load()); 947 nmethod* nm = _event_data.compiled_method_load;
937 nmethodLocker::unlock_nmethod(compiled_method_load()); 948 JvmtiExport::post_compiled_method_load(nm);
949 nmethodLocker::unlock_nmethod(nm);
938 break; 950 break;
951 }
939 case TYPE_COMPILED_METHOD_UNLOAD: 952 case TYPE_COMPILED_METHOD_UNLOAD:
940 JvmtiExport::post_compiled_method_unload( 953 JvmtiExport::post_compiled_method_unload(
941 compiled_method_unload_method_id(), 954 _event_data.compiled_method_unload.method_id,
942 compiled_method_unload_code_begin()); 955 _event_data.compiled_method_unload.code_begin);
943 break; 956 break;
944 case TYPE_FLUSH: 957 case TYPE_DYNAMIC_CODE_GENERATED:
945 JvmtiDeferredEventQueue::flush_complete(flush_state_addr()); 958 JvmtiExport::post_dynamic_code_generated_internal(
959 _event_data.dynamic_code_generated.name,
960 _event_data.dynamic_code_generated.code_begin,
961 _event_data.dynamic_code_generated.code_end);
946 break; 962 break;
947 default: 963 default:
948 ShouldNotReachHere(); 964 ShouldNotReachHere();
949 } 965 }
950 } 966 }
1063 _queue_tail = new_tail; 1079 _queue_tail = new_tail;
1064 } 1080 }
1065 } 1081 }
1066 } 1082 }
1067 1083
1068 enum {
1069 // Random - used for debugging
1070 FLUSHING = 0x50403020,
1071 FLUSHED = 0x09080706
1072 };
1073
1074 void JvmtiDeferredEventQueue::flush_queue(Thread* thread) {
1075
1076 volatile int flush_state = FLUSHING;
1077
1078 JvmtiDeferredEvent flush(JvmtiDeferredEvent::TYPE_FLUSH);
1079 flush.set_flush_state_addr((int*)&flush_state);
1080
1081 if (ServiceThread::is_service_thread(thread)) {
1082 // If we are the service thread we have to post all preceding events
1083 // Use the flush event as a token to indicate when we can stop
1084 JvmtiDeferredEvent event;
1085 {
1086 MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
1087 enqueue(flush);
1088 event = dequeue();
1089 }
1090 while (!event.is_flush_event() ||
1091 event.flush_state_addr() != &flush_state) {
1092 event.post();
1093 {
1094 MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
1095 event = dequeue();
1096 }
1097 }
1098 } else {
1099 // Wake up the service thread so it will process events. When it gets
1100 // to the flush event it will set 'flush_complete' and notify us.
1101 MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
1102 enqueue(flush);
1103 while (flush_state != FLUSHED) {
1104 assert(flush_state == FLUSHING || flush_state == FLUSHED,
1105 "only valid values for this");
1106 Service_lock->wait(Mutex::_no_safepoint_check_flag);
1107 }
1108 }
1109 }
1110
1111 void JvmtiDeferredEventQueue::flush_complete(int* state_addr) {
1112 assert(state_addr != NULL && *state_addr == FLUSHING, "must be");
1113 MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
1114 *state_addr = FLUSHED;
1115 Service_lock->notify_all();
1116 }
1117
1118 #endif // ndef KERNEL 1084 #endif // ndef KERNEL