Initial support of WinRT
authorJonathan Chambers <joncham@gmail.com>
Tue, 6 Feb 2018 08:59:25 +0000 (11:59 +0300)
committerIvan Maidanski <ivmai@mail.ru>
Tue, 6 Feb 2018 08:59:25 +0000 (11:59 +0300)
(part of commit 9379c66 from Unity-Technologies/bdwgc)

Issue #173 (bdwgc).

* include/private/gc_priv.h [MSWIN32] (GET_TIME): Use GetTickCount64
if MSWINRT_FLAVOR (instead of GetTickCount).
* include/private/gcconfig.h [_MSC_VER && _M_IX86>=300
|| _WIN32 && !__CYGWIN__ && !SYMBIAN && _M_ARM] (ARM32): Define macro.
* include/private/gcconfig.h [(_MSC_VER && _M_IX86>=300
|| _WIN32 && !__CYGWIN__ && !SYMBIAN) && !_XBOX_ONE
&& WINAPI_FAMILY==WINAPI_FAMILY_APP] (MSWINRT_FLAVOR): Likewise.
* include/private/gcconfig.h [MSWINRT_FLAVOR] (NO_GETENV): Likewise.
* include/private/gcconfig.h [X86_64 && MSWIN32] (DATAEND): Do not
define if already defined.
* misc.c [MSWIN32] (GC_win32_MessageBoxA): Do not define if
MSWINRT_FLAVOR.
* misc.c [MSWIN32] (GC_init): Call
InitializeCriticalSectionAndSpinCount() directly if MSWINRT_FLAVOR
(instead of using GetProcAddress).
* misc.c [MSWIN32 && MSWINRT_FLAVOR]: Include windows.storage.h.
* misc.c [MSWIN32 && MSWINRT_FLAVOR] (RoGetActivationFactory): Declare.
* misc.c [MSWIN32 && MSWINRT_FLAVOR] (getWinRTLogPath): New static
function.
* misc.c [MSWIN32 && MSWINRT_FLAVOR] (GC_CreateLogFile): Use
getWinRTLogPath().
* os_dep.c [GWW_VDB && MSWINRT_FLAVOR] (detect_GetWriteWatch): Use
memInfo.AllocationBase to get hK32.
* os_dep.c [USE_WINALLOC && !MSWIN_XBOX1] (GC_win32_get_mem,
GC_win32_free_heap): Do not use GlobalAlloc and GlobalFree if
MSWINRT_FLAVOR.

include/private/gc_priv.h
include/private/gcconfig.h
misc.c
os_dep.c

index 00bd3ea..1892d68 100644 (file)
@@ -432,7 +432,11 @@ typedef char * ptr_t;   /* A generic pointer to which we can add        */
 # include <windows.h>
 # include <winbase.h>
 # define CLOCK_TYPE DWORD
-# define GET_TIME(x) (void)(x = GetTickCount())
+# ifdef MSWINRT_FLAVOR
+#   define GET_TIME(x) (void)(x = (DWORD)GetTickCount64())
+# else
+#   define GET_TIME(x) (void)(x = GetTickCount())
+# endif
 # define MS_TIME_DIFF(a,b) ((long)((a)-(b)))
 #elif defined(NN_PLATFORM_CTR)
 # define CLOCK_TYPE long long
index a1933ba..c4c69a3 100644 (file)
            && !defined(SYMBIAN))
 #     if defined(__LP64__) || defined(_WIN64)
 #       define X86_64
-#     else
+#     elif defined(_M_ARM)
+#       define ARM32
+#     else /* _M_IX86 */
 #       define I386
 #     endif
 #     ifdef _XBOX_ONE
 #       define MSWIN_XBOX1
 #     else
 #       define MSWIN32  /* or Win64 */
+#       if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
+#         define MSWINRT_FLAVOR
+#       endif
 #     endif
 #     define mach_type_known
 #   endif
 #         define MPROTECT_VDB
 #       endif
 #       define GWW_VDB
-#       define DATAEND  /* not needed */
+#       ifndef DATAEND
+#         define DATAEND    /* not needed */
+#       endif
 #   endif
 # endif /* X86_64 */
 
 #  define USE_MARK_BYTES
 #endif
 
-#if defined(MSWINCE) && !defined(__CEGCC__) && !defined(NO_GETENV)
+#if (defined(MSWINCE) && !defined(__CEGCC__) || defined(MSWINRT_FLAVOR)) \
+    && !defined(NO_GETENV)
 # define NO_GETENV
 #endif
 
diff --git a/misc.c b/misc.c
index 2af1f37..6e38c0c 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -795,7 +795,7 @@ GC_API int GC_CALL GC_is_init_called(void)
   }
 #endif
 
-#if defined(MSWIN32) && (!defined(SMALL_CONFIG) \
+#if defined(MSWIN32) && !defined(MSWINRT_FLAVOR) && (!defined(SMALL_CONFIG) \
                          || (!defined(_WIN64) && defined(GC_WIN32_THREADS) \
                              && defined(CHECK_NOT_WOW64)))
   STATIC void GC_win32_MessageBoxA(const char *msg, const char *caption,
@@ -927,20 +927,27 @@ GC_API void GC_CALL GC_init(void)
 #     endif
 #   endif /* THREADS */
 #   if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS)
-     {
-#     ifndef MSWINCE
-        BOOL (WINAPI *pfn) (LPCRITICAL_SECTION, DWORD) = NULL;
-        HMODULE hK32 = GetModuleHandle(TEXT("kernel32.dll"));
-        if (hK32)
-          pfn = (BOOL (WINAPI *) (LPCRITICAL_SECTION, DWORD))
-                GetProcAddress (hK32,
-                                "InitializeCriticalSectionAndSpinCount");
-        if (pfn)
-            pfn(&GC_allocate_ml, 4000);
-        else
-#     endif /* !MSWINCE */
-        /* else */ InitializeCriticalSection (&GC_allocate_ml);
-     }
+#     ifndef SPIN_COUNT
+#       define SPIN_COUNT 4000
+#     endif
+#     ifdef MSWINRT_FLAVOR
+        InitializeCriticalSectionAndSpinCount(&GC_allocate_ml, SPIN_COUNT);
+#     else
+        {
+#         ifndef MSWINCE
+            BOOL (WINAPI *pfn)(LPCRITICAL_SECTION, DWORD) = 0;
+            HMODULE hK32 = GetModuleHandle(TEXT("kernel32.dll"));
+            if (hK32)
+              pfn = (BOOL (WINAPI *)(LPCRITICAL_SECTION, DWORD))
+                      GetProcAddress(hK32,
+                                     "InitializeCriticalSectionAndSpinCount");
+            if (pfn) {
+              pfn(&GC_allocate_ml, SPIN_COUNT);
+            } else
+#         endif /* !MSWINCE */
+          /* else */ InitializeCriticalSection(&GC_allocate_ml);
+        }
+#     endif
 #   endif /* GC_WIN32_THREADS */
 #   if (defined(MSWIN32) || defined(MSWINCE)) && defined(THREADS)
       InitializeCriticalSection(&GC_write_cs);
@@ -1410,9 +1417,97 @@ GC_API void GC_CALL GC_enable_incremental(void)
 #   define IF_NEED_TO_LOCK(x)
 # endif /* !THREADS */
 
+# ifdef MSWINRT_FLAVOR
+#   include <windows.storage.h>
+
+    /* This API is defined in roapi.h, but we cannot include it here    */
+    /* since it does not compile in C.                                  */
+    DECLSPEC_IMPORT HRESULT WINAPI RoGetActivationFactory(
+                                        HSTRING activatableClassId,
+                                        REFIID iid, void** factory);
+
+    static GC_bool getWinRTLogPath(wchar_t* buf, size_t bufLen)
+    {
+      static const GUID kIID_IApplicationDataStatics = {
+        0x5612147B, 0xE843, 0x45E3,
+        0x94, 0xD8, 0x06, 0x16, 0x9E, 0x3C, 0x8E, 0x17
+      };
+      static const GUID kIID_IStorageItem = {
+        0x4207A996, 0xCA2F, 0x42F7,
+        0xBD, 0xE8, 0x8B, 0x10, 0x45, 0x7A, 0x7F, 0x30
+      };
+      GC_bool result = FALSE;
+      HSTRING_HEADER appDataClassNameHeader;
+      HSTRING appDataClassName;
+      __x_ABI_CWindows_CStorage_CIApplicationDataStatics* appDataStatics = 0;
+
+      GC_ASSERT(bufLen > 0);
+      if (SUCCEEDED(WindowsCreateStringReference(
+                      RuntimeClass_Windows_Storage_ApplicationData,
+                      (sizeof(RuntimeClass_Windows_Storage_ApplicationData)-1)
+                        / sizeof(wchar_t),
+                      &appDataClassNameHeader, &appDataClassName))
+          && SUCCEEDED(RoGetActivationFactory(appDataClassName,
+                                              &kIID_IApplicationDataStatics,
+                                              &appDataStatics))) {
+        __x_ABI_CWindows_CStorage_CIApplicationData* appData = NULL;
+        __x_ABI_CWindows_CStorage_CIStorageFolder* tempFolder = NULL;
+        __x_ABI_CWindows_CStorage_CIStorageItem* tempFolderItem = NULL;
+        HSTRING tempPath = NULL;
+
+        if (SUCCEEDED(appDataStatics->lpVtbl->get_Current(appDataStatics,
+                                                          &appData))
+            && SUCCEEDED(appData->lpVtbl->get_TemporaryFolder(appData,
+                                                              &tempFolder))
+            && SUCCEEDED(tempFolder->lpVtbl->QueryInterface(tempFolder,
+                                                        &kIID_IStorageItem,
+                                                        &tempFolderItem))
+            && SUCCEEDED(tempFolderItem->lpVtbl->get_Path(tempFolderItem,
+                                                          &tempPath))) {
+          UINT32 tempPathLen;
+          const wchar_t* tempPathBuf =
+                          WindowsGetStringRawBuffer(tempPath, &tempPathLen);
+
+          buf[0] = '\0';
+          if (wcsncat_s(buf, bufLen, tempPathBuf, tempPathLen) == 0
+              && wcscat_s(buf, bufLen, L"\\") == 0
+              && wcscat_s(buf, bufLen, TEXT(GC_LOG_STD_NAME)) == 0)
+            result = TRUE;
+          WindowsDeleteString(tempPath);
+        }
+
+        if (tempFolderItem != NULL)
+          tempFolderItem->lpVtbl->Release(tempFolderItem);
+        if (tempFolder != NULL)
+          tempFolder->lpVtbl->Release(tempFolder);
+        if (appData != NULL)
+          appData->lpVtbl->Release(appData);
+        appDataStatics->lpVtbl->Release(appDataStatics);
+      }
+      return result;
+    }
+# endif /* MSWINRT_FLAVOR */
+
   STATIC HANDLE GC_CreateLogFile(void)
   {
     HANDLE hFile;
+# ifdef MSWINRT_FLAVOR
+      TCHAR pathBuf[_MAX_PATH + 0x10]; /* buffer for path + ext */
+
+      hFile = INVALID_HANDLE_VALUE;
+      if (getWinRTLogPath(pathBuf, _MAX_PATH + 1)) {
+        CREATEFILE2_EXTENDED_PARAMETERS extParams;
+
+        BZERO(&extParams, sizeof(extParams));
+        extParams.dwSize = sizeof(extParams);
+        extParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
+        extParams.dwFileFlags = GC_print_stats == VERBOSE ? 0
+                                    : FILE_FLAG_WRITE_THROUGH;
+        hFile = CreateFile2(pathBuf, GENERIC_WRITE, FILE_SHARE_READ,
+                            CREATE_ALWAYS, &extParams);
+      }
+
+# else
     TCHAR *logPath;
     BOOL appendToFile = FALSE;
 #   if !defined(NO_GETENV_WIN32) || !defined(OLD_WIN32_LOG_FILE)
@@ -1451,6 +1546,7 @@ GC_API void GC_CALL GC_enable_incremental(void)
                             /* immediately flush writes unless very verbose */
                             FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
                        NULL /* hTemplateFile */);
+
 #   ifndef NO_GETENV_WIN32
       if (appendToFile && hFile != INVALID_HANDLE_VALUE) {
         LONG posHigh = 0;
@@ -1458,6 +1554,7 @@ GC_API void GC_CALL GC_enable_incremental(void)
                                   /* Seek to file end (ignoring any error) */
       }
 #   endif
+# endif
     return hFile;
   }
 
index cd089c7..0155c20 100644 (file)
--- a/os_dep.c
+++ b/os_dep.c
@@ -1644,7 +1644,18 @@ void GC_register_data_segments(void)
         }
 #     endif
 
-      hK32 = GetModuleHandle(TEXT("kernel32.dll"));
+#     ifdef MSWINRT_FLAVOR
+        {
+          MEMORY_BASIC_INFORMATION memInfo;
+          SIZE_T result = VirtualQuery(GetProcAddress,
+                                       &memInfo, sizeof(memInfo));
+          if (result != sizeof(memInfo))
+            ABORT("Weird VirtualQuery result");
+          hK32 = (HMODULE)memInfo.AllocationBase;
+        }
+#     else
+        hK32 = GetModuleHandle(TEXT("kernel32.dll"));
+#     endif
       if (hK32 != (HMODULE)0 &&
           (GetWriteWatch_func = (GetWriteWatch_type)GetProcAddress(hK32,
                                                 "GetWriteWatch")) != NULL) {
@@ -2352,7 +2363,7 @@ void * os2_alloc(size_t bytes)
 # ifndef USE_WINALLOC
     result = GC_unix_get_mem(bytes);
 # else
-#   ifdef MSWIN32
+#   if defined(MSWIN32) && !defined(MSWINRT_FLAVOR)
       if (GLOBAL_ALLOC_TEST) {
         /* VirtualAlloc doesn't like PAGE_EXECUTE_READWRITE.    */
         /* There are also unconfirmed rumors of other           */
@@ -2409,26 +2420,27 @@ void * os2_alloc(size_t bytes)
 
   GC_API void GC_CALL GC_win32_free_heap(void)
   {
-#   ifndef CYGWIN32
-      if (GLOBAL_ALLOC_TEST)
-#   endif
-    {
-      while (GC_n_heap_bases-- > 0) {
-#       ifdef CYGWIN32
-          /* FIXME: Is it OK to use non-GC free() here? */
-#       else
-          GlobalFree(GC_heap_bases[GC_n_heap_bases]);
-#       endif
-        GC_heap_bases[GC_n_heap_bases] = 0;
-      }
-    } /* else */
-#   ifndef CYGWIN32
-      else {
-        /* Avoiding VirtualAlloc leak. */
-        while (GC_n_heap_bases > 0) {
-          VirtualFree(GC_heap_bases[--GC_n_heap_bases], 0, MEM_RELEASE);
+#   ifndef MSWINRT_FLAVOR
+#     ifndef CYGWIN32
+        if (GLOBAL_ALLOC_TEST)
+#     endif
+      {
+        while (GC_n_heap_bases-- > 0) {
+#         ifdef CYGWIN32
+            /* FIXME: Is it OK to use non-GC free() here? */
+#         else
+            GlobalFree(GC_heap_bases[GC_n_heap_bases]);
+#         endif
           GC_heap_bases[GC_n_heap_bases] = 0;
         }
+        return;
+      }
+#   endif
+#   ifndef CYGWIN32
+      /* Avoiding VirtualAlloc leak. */
+      while (GC_n_heap_bases > 0) {
+        VirtualFree(GC_heap_bases[--GC_n_heap_bases], 0, MEM_RELEASE);
+        GC_heap_bases[GC_n_heap_bases] = 0;
       }
 #   endif
   }