diff --git a/src/pal/inc/pal.h b/src/pal/inc/pal.h index 4ed5e9267e87..26252c264260 100644 --- a/src/pal/inc/pal.h +++ b/src/pal/inc/pal.h @@ -5447,12 +5447,17 @@ FlushProcessWriteBuffers(); typedef void (*PAL_ActivationFunction)(CONTEXT *context); +PALIMPORT +VOID +PALAPI +PAL_SetActivationFunction( + IN PAL_ActivationFunction pActivationFunction); + PALIMPORT BOOL PALAPI PAL_InjectActivation( - IN HANDLE hThread, - IN PAL_ActivationFunction pActivationFunction + IN HANDLE hThread ); #define VER_PLATFORM_WIN32_WINDOWS 1 diff --git a/src/pal/src/exception/signal.cpp b/src/pal/src/exception/signal.cpp index 74b69f5a0b2a..444639a9579d 100644 --- a/src/pal/src/exception/signal.cpp +++ b/src/pal/src/exception/signal.cpp @@ -101,6 +101,9 @@ int g_signalPipe[2] = { 0, 0 }; DWORD g_dwExternalSignalHandlerThreadId = 0; +// Activation function that gets called when an activation is injected into a thread. +PAL_ActivationFunction g_activationFunction = NULL; + /* public function definitions ************************************************/ /*++ @@ -565,6 +568,28 @@ static void sigbus_handler(int code, siginfo_t *siginfo, void *context) } } +/*++ +Function: + PAL_SetActivationFunction + + Register an activation function that gets called when an activation is injected + into a thread. + +Parameters: + pActivationFunction - activation function + +Return value: + None +--*/ +PALIMPORT +VOID +PALAPI +PAL_SetActivationFunction( + IN PAL_ActivationFunction pActivationFunction) +{ + g_activationFunction = pActivationFunction; +} + /*++ Function : inject_activation_handler @@ -582,8 +607,7 @@ static void inject_activation_handler(int code, siginfo_t *siginfo, void *contex // Only accept activations from the current process if (siginfo->si_pid == getpid()) { - PAL_ActivationFunction activation = (PAL_ActivationFunction)siginfo->si_value.sival_ptr; - if (activation != NULL) + if (g_activationFunction != NULL) { native_context_t *ucontext = (native_context_t *)context; @@ -593,7 +617,7 @@ static void inject_activation_handler(int code, siginfo_t *siginfo, void *contex &winContext, CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT); - activation(&winContext); + g_activationFunction(&winContext); // Activation function may have modified the context, so update it. CONTEXTToNativeContext(&winContext, ucontext); @@ -613,12 +637,9 @@ Parameters : (no return value) --*/ -void InjectActivationInternal(CorUnix::CPalThread* pThread, PAL_ActivationFunction activationFunction) +void InjectActivationInternal(CorUnix::CPalThread* pThread) { -#if HAVE_PTHREAD_SIGQUEUE - sigval value; - value.sival_ptr = (void*)activationFunction; - int status = pthread_sigqueue(pThread->GetPThreadSelf(), INJECT_ACTIVATION_SIGNAL, value); + int status = pthread_kill(pThread->GetPThreadSelf(), INJECT_ACTIVATION_SIGNAL); if (status != 0) { // Failure to send the signal is fatal. There are only two cases when sending @@ -626,20 +647,17 @@ void InjectActivationInternal(CorUnix::CPalThread* pThread, PAL_ActivationFuncti // if the thread doesn't exist anymore. abort(); } -#else - ASSERT("InjectActivationInternal not yet implemented on this platform!"); -#endif } /*++ Function: PAL_InjectActivation -Interrupt the specified thread and have it call the activation function passed in +Interrupt the specified thread and have it call an activation function registered +using the PAL_SetActivationFunction Parameters: hThread - handle of the target thread -activationFunction - function to call Return: TRUE if it succeeded, FALSE otherwise. @@ -647,11 +665,10 @@ TRUE if it succeeded, FALSE otherwise. BOOL PALAPI PAL_InjectActivation( - IN HANDLE hThread, - IN PAL_ActivationFunction pActivationFunction) + IN HANDLE hThread) { PERF_ENTRY(PAL_InjectActivation); - ENTRY("PAL_InjectActivation(hThread=%p, pActivationFunction=%p)\n", hThread, pActivationFunction); + ENTRY("PAL_InjectActivation(hThread=%p)\n", hThread); CPalThread *pCurrentThread; CPalThread *pTargetThread; @@ -669,7 +686,7 @@ PAL_InjectActivation( if (palError == NO_ERROR) { - InjectActivationInternal(pTargetThread, pActivationFunction); + InjectActivationInternal(pTargetThread); } else { diff --git a/src/vm/ceemain.cpp b/src/vm/ceemain.cpp index c6e67d0e8cf2..c1899f24fb56 100644 --- a/src/vm/ceemain.cpp +++ b/src/vm/ceemain.cpp @@ -1160,7 +1160,7 @@ void EEStartupHelper(COINITIEE fFlags) #endif // PROFILING_SUPPORTED InitializeExceptionHandling(); - + // // Install our global exception filter // diff --git a/src/vm/threads.cpp b/src/vm/threads.cpp index 007d233f14c5..e90a220c64d8 100644 --- a/src/vm/threads.cpp +++ b/src/vm/threads.cpp @@ -1691,6 +1691,8 @@ void InitThreadManager() // Randomize OBJREF_HASH to handle hash collision. Thread::OBJREF_HASH = OBJREF_TABSIZE - (DbgGetEXETimeStamp()%10); #endif // _DEBUG + + ThreadSuspend::Initialize(); } diff --git a/src/vm/threadsuspend.cpp b/src/vm/threadsuspend.cpp index be220f334a5f..cc9080116d72 100644 --- a/src/vm/threadsuspend.cpp +++ b/src/vm/threadsuspend.cpp @@ -8370,7 +8370,7 @@ bool Thread::InjectGcSuspension() hThread = GetThreadHandle(); if (hThread != INVALID_HANDLE_VALUE && hThread != SWITCHOUT_HANDLE_VALUE) { - ::PAL_InjectActivation(hThread, HandleGCSuspensionForInterruptedThread); + ::PAL_InjectActivation(hThread); return true; } @@ -8379,6 +8379,14 @@ bool Thread::InjectGcSuspension() #endif // FEATURE_HIJACK && PLATFORM_UNIX +// Initialize thread suspension support +void ThreadSuspend::Initialize() +{ +#if defined(FEATURE_HIJACK) && defined(PLATFORM_UNIX) + ::PAL_SetActivationFunction(HandleGCSuspensionForInterruptedThread); +#endif +} + #ifdef _DEBUG BOOL Debug_IsLockedViaThreadSuspension() { diff --git a/src/vm/threadsuspend.h b/src/vm/threadsuspend.h index 73f2b8b80361..df88629ad2f8 100644 --- a/src/vm/threadsuspend.h +++ b/src/vm/threadsuspend.h @@ -197,6 +197,9 @@ class ThreadSuspend static HRESULT SuspendRuntime(ThreadSuspend::SUSPEND_REASON reason); static void ResumeRuntime(BOOL bFinishedGC, BOOL SuspendSucceded); + // Initialize thread suspension support + static void Initialize(); + private: static CLREvent * g_pGCSuspendEvent;