summaryrefslogtreecommitdiff
path: root/src/vm/synchronizationcontextnative.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/synchronizationcontextnative.cpp')
-rw-r--r--src/vm/synchronizationcontextnative.cpp160
1 files changed, 160 insertions, 0 deletions
diff --git a/src/vm/synchronizationcontextnative.cpp b/src/vm/synchronizationcontextnative.cpp
new file mode 100644
index 0000000000..4c37b75c73
--- /dev/null
+++ b/src/vm/synchronizationcontextnative.cpp
@@ -0,0 +1,160 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Implementation: SynchronizationContextNative.cpp
+**
+**
+** Purpose: Native methods on System.Threading.SynchronizationContext.
+**
+**
+===========================================================*/
+
+#include "common.h"
+
+#ifdef FEATURE_APPX
+#include <roapi.h>
+#include <windows.ui.core.h>
+#endif
+#include "synchronizationcontextnative.h"
+
+#ifdef FEATURE_SYNCHRONIZATIONCONTEXT_WAIT
+FCIMPL3(DWORD, SynchronizationContextNative::WaitHelper, PTRArray *handleArrayUNSAFE, CLR_BOOL waitAll, DWORD millis)
+{
+ FCALL_CONTRACT;
+
+ DWORD ret = 0;
+
+ PTRARRAYREF handleArrayObj = (PTRARRAYREF) handleArrayUNSAFE;
+ HELPER_METHOD_FRAME_BEGIN_RET_1(handleArrayObj);
+
+ CQuickArray<HANDLE> qbHandles;
+ int cHandles = handleArrayObj->GetNumComponents();
+
+ // Since DoAppropriateWait could cause a GC, we need to copy the handles to an unmanaged block
+ // of memory to ensure they aren't relocated during the call to DoAppropriateWait.
+ qbHandles.AllocThrows(cHandles);
+ memcpy(qbHandles.Ptr(), handleArrayObj->GetDataPtr(), cHandles * sizeof(HANDLE));
+
+ Thread * pThread = GetThread();
+ ret = pThread->DoAppropriateWait(cHandles, qbHandles.Ptr(), waitAll, millis,
+ (WaitMode)(WaitMode_Alertable | WaitMode_IgnoreSyncCtx));
+
+ HELPER_METHOD_FRAME_END();
+ return ret;
+}
+FCIMPLEND
+#endif // #ifdef FEATURE_SYNCHRONIZATIONCONTEXT_WAIT
+
+#ifdef FEATURE_APPX
+
+Volatile<ABI::Windows::UI::Core::ICoreWindowStatic*> g_pICoreWindowStatic;
+
+void* QCALLTYPE SynchronizationContextNative::GetWinRTDispatcherForCurrentThread()
+{
+ QCALL_CONTRACT;
+ void* result = NULL;
+ BEGIN_QCALL;
+
+ _ASSERTE(WinRTSupported());
+
+ //
+ // Get access to ICoreWindow's statics. We grab just one ICoreWindowStatic for the whole process.
+ //
+ ABI::Windows::UI::Core::ICoreWindowStatic* pICoreWindowStatic = g_pICoreWindowStatic;
+ if (pICoreWindowStatic == NULL)
+ {
+ SafeComHolderPreemp<ABI::Windows::UI::Core::ICoreWindowStatic> pNewICoreWindowStatic;
+ {
+ HRESULT hr = clr::winrt::GetActivationFactory(RuntimeClass_Windows_UI_Core_CoreWindow, (ABI::Windows::UI::Core::ICoreWindowStatic**)pNewICoreWindowStatic.GetAddr());
+
+ //
+ // Older Windows builds don't support ICoreWindowStatic. We should just return a null CoreDispatcher
+ // in that case, rather than throwing.
+ //
+ if (hr != E_NOTIMPL)
+ IfFailThrow(hr);
+ }
+
+ if (pNewICoreWindowStatic != NULL)
+ {
+ ABI::Windows::UI::Core::ICoreWindowStatic* old = InterlockedCompareExchangeT<ABI::Windows::UI::Core::ICoreWindowStatic*>(&g_pICoreWindowStatic, pNewICoreWindowStatic, NULL);
+ if (old == NULL)
+ {
+ pNewICoreWindowStatic.SuppressRelease();
+ pICoreWindowStatic = pNewICoreWindowStatic;
+ }
+ else
+ {
+ pICoreWindowStatic = old;
+ }
+ }
+ }
+
+
+ if (pICoreWindowStatic != NULL)
+ {
+ //
+ // Get the current ICoreWindow
+ //
+ SafeComHolderPreemp<ABI::Windows::UI::Core::ICoreWindow> pCoreWindow;
+
+ //
+ // workaround: we're currently ignoring the HRESULT from get_Current, because Windows is returning errors for threads that have no CoreWindow.
+ // A better behavior would be to return S_OK, with a NULL CoreWindow. If/when Windows does the right thing here, we can change this
+ // back to checking the HRESULT.
+ //
+ pICoreWindowStatic->GetForCurrentThread(&pCoreWindow);
+
+ if (pCoreWindow != NULL)
+ {
+ //
+ // Get the ICoreDispatcher for this window
+ //
+ SafeComHolderPreemp<ABI::Windows::UI::Core::ICoreDispatcher> pCoreDispatcher;
+ IfFailThrow(pCoreWindow->get_Dispatcher(&pCoreDispatcher));
+
+ if (pCoreDispatcher != NULL)
+ {
+ //
+ // Does the dispatcher belong to the current thread?
+ //
+ boolean hasThreadAccess = FALSE;
+ IfFailThrow(pCoreDispatcher->get_HasThreadAccess(&hasThreadAccess));
+ if (hasThreadAccess)
+ {
+ //
+ // This is the dispatcher for the current thread. Return it.
+ //
+ pCoreDispatcher.SuppressRelease();
+ result = (void*)pCoreDispatcher;
+ }
+ }
+ }
+ }
+
+ END_QCALL;
+ return result;
+}
+
+void SynchronizationContextNative::Cleanup()
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_ANY;
+ } CONTRACTL_END;
+
+ if (g_pICoreWindowStatic)
+ {
+ SafeRelease(g_pICoreWindowStatic);
+ g_pICoreWindowStatic = NULL;
+ }
+}
+
+
+
+#endif //FEATURE_APPX