Index: trunk/vm/thread/src/thread_java_basic.c =================================================================== --- trunk/vm/thread/src/thread_java_basic.c (revision 486089) +++ trunk/vm/thread/src/thread_java_basic.c (working copy) @@ -406,14 +406,17 @@ jvmti_thread_t tm_java_thread; jobject excn; + assert(hythread_is_suspend_enabled()); + + hythread_suspend_disable(); + tm_native_thread = hythread_self(); tm_java_thread = hythread_get_private_data(tm_native_thread); excn = tm_java_thread->stop_exception; - tm_native_thread->suspend_request = 0; - hysem_post(tm_native_thread->resume_event); - jthread_throw_exception_object(excn); + + hythread_suspend_enable(); } /** Index: trunk/vm/thread/src/thread_native_basic.c =================================================================== --- trunk/vm/thread/src/thread_native_basic.c (revision 486089) +++ trunk/vm/thread/src/thread_native_basic.c (working copy) @@ -653,7 +653,10 @@ assert (status == TM_ERROR_NONE); status = hycond_create(&ptr->condition); assert (status == TM_ERROR_NONE); - + + ptr->safepoint_callback = NULL; + ptr->callback_suspend_request = 0; + ptr->state = TM_THREAD_STATE_ALLOCATED; return ptr; } @@ -681,7 +684,10 @@ assert (status == TM_ERROR_NONE); status = hysem_set(thread->resume_event, 0); assert (status == TM_ERROR_NONE); - + + thread->safepoint_callback = NULL; + thread->callback_suspend_request = 0; + thread->state = TM_THREAD_STATE_ALLOCATED; } Index: trunk/vm/thread/src/thread_native_suspend.c =================================================================== --- trunk/vm/thread/src/thread_native_suspend.c (revision 486089) +++ trunk/vm/thread/src/thread_native_suspend.c (working copy) @@ -151,28 +151,38 @@ static void thread_safe_point_impl(hythread_t thread) { hythread_event_callback_proc callback_func; + if(thread->suspend_request >0) { int old_status = thread->suspend_disable_count; do { TRACE(("TM: safe point enter: thread: %p count: %d dis count: %d", thread, thread->suspend_request, thread->suspend_disable_count)); - + + thread->suspend_disable_count = 0; + apr_memory_rw_barrier(); + if (thread->safepoint_callback) { - thread->suspend_disable_count = 1; - // Clear callback (this is one-time event) - callback_func = thread->safepoint_callback; - thread->safepoint_callback = NULL; + // Wait until the current thread gets suspend request from + // hythread_set_safe_point_callback + while (!thread->callback_suspend_request) { + hythread_yield(); + } + + thread->callback_suspend_request = 0; // since set callback suspended the thread // resore its original state - hythread_resume(tm_self_tls); - callback_func(); + hythread_resume(thread); + + // Clear callback (this is one-time event) + callback_func = thread->safepoint_callback; + thread->safepoint_callback = NULL; + + // Execute the callback. + callback_func(); } - thread->suspend_disable_count = 0; - - apr_memory_rw_barrier(); // code for Ipf that support StackIterator and immmediate suspend // notify suspender // hylatch_count_down(thread->safe_region_event); @@ -315,7 +325,6 @@ // If there was request for suspension, decrease the request counter // printf("resume other now lock %d %d %d %d\n",tm_self_tls->thread_id,tm_self_tls->suspend_disable_count,thread->thread_id,thread->suspend_disable_count); if(thread->suspend_request > 0) { - if (thread->safepoint_callback && thread->suspend_request < 2) return; apr_atomic_dec32((apr_uint32_t *)&(thread->suspend_request)); if(thread->suspend_request == 0) { // Notify the thread that it may wake up now @@ -337,23 +346,33 @@ */ IDATA hythread_set_safepoint_callback(hythread_t thread, tm_thread_event_callback_proc callback) { IDATA status; - while (apr_atomic_casptr((volatile void **)&thread->safepoint_callback, (void *)callback, (void *)NULL) != NULL); - if(tm_self_tls == thread) { - int old_status = thread->suspend_disable_count; - thread->suspend_disable_count = 1; - hythread_suspend(); - thread->suspend_disable_count = old_status; + + // It can be a source of a deadlock if current thread is not in suspend enabled state. + // The specified thread can be waiting when the current thread reaches a safe point. + assert(hythread_is_suspend_enabled()); + + if (tm_self_tls == thread) { + // Just execute the callback. + callback(); } else { - //we will not have notification from the - //target thread if safe_point call back will not exit - //// + // WARNING: don't send suspend request before the callback is set. + // It may lead to a deadlock if the previous callback function waits while + // it will be valid to switch to suspend disabled state! + + // Set the callback atomically. + while (apr_atomic_casptr((volatile void **)&thread->safepoint_callback, (void *)callback, (void *)NULL) != NULL); + + // Make sure the callback will be executed before leaving safepoint or saferegion. send_suspend_request(thread); - //let the thread execute safe point in the case it's already suspended - //// - status = hysem_post(thread->resume_event); - + + // Notify about suspend request. + thread->callback_suspend_request = 1; + + // Let the thread to spin one more time to detect the callback. + hysem_post(thread->resume_event); } - + + if (thread->current_condition) { status=hycond_notify_all(thread->current_condition); assert (status == TM_ERROR_NONE); Index: trunk/vm/thread/src/thread_private.h =================================================================== --- trunk/vm/thread/src/thread_private.h (revision 486089) +++ trunk/vm/thread/src/thread_private.h (working copy) @@ -204,7 +204,12 @@ */ hythread_event_callback_proc safepoint_callback; + /** + * + */ + int callback_suspend_request; + // Basic manipulation fields /**