Squashed commit of the following:
authorDavid Mason <davmason@microsoft.com>
Thu, 26 May 2016 02:20:54 +0000 (19:20 -0700)
committerDavid Mason <davmason@microsoft.com>
Wed, 1 Jun 2016 18:03:26 +0000 (11:03 -0700)
commit dotnet/coreclr@45d11dde6acdc3def0a13302c527e3c7a662b009
Author: David Mason <davmason@microsoft.com>
Date:   Wed May 25 19:00:10 2016 -0700

    Squashed commit of the following:

    commit dotnet/coreclr@f586c5552d8225f13b5a0476f5bdf9362ba9ee8d
    Author: Lee Culver <leculver@microsoft.com>
    Date:   Wed May 25 14:17:45 2016 -0700

        Fix heap dump GC type to be Induced

        Previously we didn't set the GC type to be "Induced" when collecting a heap dump.  This would cause perfview to ignore the GC.

    commit dotnet/coreclr@78866dfdcc15ebade0a2faeb6af9a5b7f5e0a170
    Author: Lee Culver <leculver@microsoft.com>
    Date:   Wed May 25 13:18:41 2016 -0700

        Enable LTTng events for creating a gcdump

        There were a handful of events that were not properly enabled on linux.  This change adds enables the remaining events to allow heap dumps.

    commit dotnet/coreclr@04d3d6c3d9a1c87e88bc1db91f717481f21874bc
    Author: Lee Culver <leculver@microsoft.com>
    Date:   Tue May 24 12:57:16 2016 -0700

        Fix BulkTypeEvents

        The buffer used for BulkTypeEvents was defined as a BYTE** instead of BYTE*.  This lead to incorrectly written BulkTypeEvents.

    commit dotnet/coreclr@8ceab5828e8101b134beb0175b1842487607636c
    Author: David Mason <davmason@microsoft.com>
    Date:   Wed May 18 11:21:12 2016 -0700

        Add logic for finalizer thread to check to see if a heap dump is required.

    commit dotnet/coreclr@cd64b4884d639ce90e4192975533f5e873bd1cb3
    Author: Lee Culver <leculver@microsoft.com>
    Date:   Thu May 19 14:24:01 2016 -0700

        Special case BulkType LTTng event

        The BulkType LTTng event does not have a real element size.  Instead each element is variable length.  This change updates the FireBulkType method to allow us to pass the correct size to LTTng.

    commit dotnet/coreclr@f8ab762106188bc124af802ec0490ef8375412b5
    Merge: 77495aa f0d9ab4
    Author: Lee Culver <leculver@microsoft.com>
    Date:   Thu May 19 13:49:43 2016 -0700

        Merge branch 'gc-events' of github.com:leculver/coreclr into gc-events

    commit dotnet/coreclr@f0d9ab4e52c69b45d2d169983c23ab5263edb5c0
    Author: Lee Culver <leculver@microsoft.com>
    Date:   Thu May 19 12:51:01 2016 -0700

        Enable BulkType LTTng events on linux

        Emit calls to FireBulkType events on linux.  This commit enables the code, but currently the wrong size is used in the etw subsystem (this function must be special cased).

    commit dotnet/coreclr@25c682ce49f51298f011046faa50443c569943b7
    Author: Lee Culver <leculver@microsoft.com>
    Date:   Wed May 18 12:06:05 2016 -0700

        Fix multiple LTTng issues

        - Only emit LTTng events when LTTng is enabled.  We now use the tracepoint_enabled macro to check if an event is enabled...when the version of lttng is installed that supports it.
        - Unsplit LTTng events.  Previously we split LTTng events when they exceeded the field limit of LTTng.  Now we emit those events as a raw byte array so that it matches their windows ETW counterparts byte-for-byte.
        - Emit any event with a struct or embedded array as a raw byte array too.  The structure of memory that LTTng emits is incompatible with our ETW parsing.  Changing events with struct/array fields greatly simplifies the parsing of events.

    commit dotnet/coreclr@77495aa1b3415dcee8d4b6e8eb1d0b5cb921f821
    Merge: 754596d f77577c
    Author: Lee Culver <leculver@microsoft.com>
    Date:   Tue May 17 18:24:55 2016 -0700

        Merge branch 'master' of github.com:leculver/coreclr

    commit dotnet/coreclr@754596d9c51d07db9267148a20f81c786f719312
    Author: Lee Culver <leculver@microsoft.com>
    Date:   Tue May 17 18:21:54 2016 -0700

        Squashed commit of the following:

        commit dotnet/coreclr@f77577c1d7c552de9e75f6fb98a656a1d09bf8b2
        Author: Lee Culver <leculver@microsoft.com>
        Date:   Tue May 17 18:04:18 2016 -0700

            Properly handle arrays in LTTng

            Arrays were not being properly handled by the LTTng code generator.

        commit dotnet/coreclr@390e998719e050a4e61b29bef4c8f8ecbff3423f
        Author: Lee Culver <leculver@microsoft.com>
        Date:   Tue May 17 11:21:07 2016 -0700

            Manually write events with structs

            Manually write events to LTTng which have structs embedded in them.

        commit dotnet/coreclr@54ae7c79f3c96987504cece302513ac9215afbfe
        Author: Lee Culver <leculver@microsoft.com>
        Date:   Tue May 17 09:12:45 2016 -0700

            Fix issue with struct sizes

            Struct sizes were not properly calculated for manually saved events.

        commit dotnet/coreclr@d4e59b1b8b18822e551e585ebe006e5b66066bf8
        Author: Lee Culver <leculver@microsoft.com>
        Date:   Mon May 16 20:57:33 2016 -0700

            Fix tests

            Tests were not being generated properly, as they skipped a parameter.
            This is now fixed.

        commit dotnet/coreclr@91d68c7ee36f28b1d9de8d0242edcd078416dc80
        Author: Lee Culver <leculver@microsoft.com>
        Date:   Wed May 11 17:41:23 2016 -0700

            Remove excess fields in LTTng stream

            Extra fields were inserted into LTTng to calculate the size of struct
            pointers.  Now this calculation is done natively without needing to
            insert the extra fields.

        commit dotnet/coreclr@3bf826f5e36637ff5188d0205510d7236458075a
        Author: Lee Culver <leculver@microsoft.com>
        Date:   Tue May 10 10:00:39 2016 -0700

            Re-enable dynamic linking to fix a load issue

            Was getting a loader issue on startup, disabling static linking for now.

        commit dotnet/coreclr@aacb45ff675d2299df938493416f875096ec446c
        Author: Lee Culver <leculver@microsoft.com>
        Date:   Thu Apr 28 20:56:01 2016 -0700

            Unsplit lttng events

            LTTng has a limitation in that it cannot emit events with more than 9
            parameters.  Previously we would split these events into multiple
            events.  However this proves to be very difficult to consume with
            TraceEvent.  Instead we now pack the parameters into a byte array an
            emit the byte array + length as a single event, avoiding the need to
            recombine events later.

        commit dotnet/coreclr@a9a630da28d42132c2e8929909e86545fbe630c9
        Author: Lee Culver <leculver@microsoft.com>
        Date:   Wed Apr 20 13:31:33 2016 -0700

            Only emit LTTng events when they are enabeld.

            This changes adds a check for tracepoint_enabled (when that feature is available).
            This change also statically compiles against the LTTng libraries (instead of dynamically) to avoid using entrypoints that may not be there if compiled against a different lttng that lacks the tracepoint_enabled entrypoint.

    commit dotnet/coreclr@f77577c1d7c552de9e75f6fb98a656a1d09bf8b2
    Author: Lee Culver <leculver@microsoft.com>
    Date:   Tue May 17 18:04:18 2016 -0700

        Properly handle arrays in LTTng

        Arrays were not being properly handled by the LTTng code generator.

    commit dotnet/coreclr@390e998719e050a4e61b29bef4c8f8ecbff3423f
    Author: Lee Culver <leculver@microsoft.com>
    Date:   Tue May 17 11:21:07 2016 -0700

        Manually write events with structs

        Manually write events to LTTng which have structs embedded in them.

    commit dotnet/coreclr@54ae7c79f3c96987504cece302513ac9215afbfe
    Author: Lee Culver <leculver@microsoft.com>
    Date:   Tue May 17 09:12:45 2016 -0700

        Fix issue with struct sizes

        Struct sizes were not properly calculated for manually saved events.

    commit dotnet/coreclr@d4e59b1b8b18822e551e585ebe006e5b66066bf8
    Author: Lee Culver <leculver@microsoft.com>
    Date:   Mon May 16 20:57:33 2016 -0700

        Fix tests

        Tests were not being generated properly, as they skipped a parameter.
        This is now fixed.

    commit dotnet/coreclr@91d68c7ee36f28b1d9de8d0242edcd078416dc80
    Author: Lee Culver <leculver@microsoft.com>
    Date:   Wed May 11 17:41:23 2016 -0700

        Remove excess fields in LTTng stream

        Extra fields were inserted into LTTng to calculate the size of struct
        pointers.  Now this calculation is done natively without needing to
        insert the extra fields.

    commit dotnet/coreclr@3bf826f5e36637ff5188d0205510d7236458075a
    Author: Lee Culver <leculver@microsoft.com>
    Date:   Tue May 10 10:00:39 2016 -0700

        Re-enable dynamic linking to fix a load issue

        Was getting a loader issue on startup, disabling static linking for now.

    commit dotnet/coreclr@aacb45ff675d2299df938493416f875096ec446c
    Author: Lee Culver <leculver@microsoft.com>
    Date:   Thu Apr 28 20:56:01 2016 -0700

        Unsplit lttng events

        LTTng has a limitation in that it cannot emit events with more than 9
        parameters.  Previously we would split these events into multiple
        events.  However this proves to be very difficult to consume with
        TraceEvent.  Instead we now pack the parameters into a byte array an
        emit the byte array + length as a single event, avoiding the need to
        recombine events later.

    commit dotnet/coreclr@a9a630da28d42132c2e8929909e86545fbe630c9
    Author: Lee Culver <leculver@microsoft.com>
    Date:   Wed Apr 20 13:31:33 2016 -0700

        Only emit LTTng events when they are enabeld.

        This changes adds a check for tracepoint_enabled (when that feature is available).
        This change also statically compiles against the LTTng libraries (instead of dynamically) to avoid using entrypoints that may not be there if compiled against a different lttng that lacks the tracepoint_enabled entrypoint.

Commit migrated from https://github.com/dotnet/coreclr/commit/223256668d2c73d2ca2a54a1373742b905755ee3

src/coreclr/src/inc/eventtracebase.h
src/coreclr/src/scripts/genXplatLttng.py
src/coreclr/src/vm/eventtrace.cpp
src/coreclr/src/vm/eventtracepriv.h
src/coreclr/src/vm/finalizerthread.cpp
src/coreclr/src/vm/finalizerthread.h
src/coreclr/src/vm/vars.hpp

index 82332b5..f773a7c 100644 (file)
@@ -298,12 +298,6 @@ extern "C" {
 
 #include "clretwallmain.h"
 
-// The bulk type event is too complex for MC.exe to auto-generate proper code.
-// Use code:BulkTypeEventLogger instead.
-#ifdef FireEtwBulkType
-#undef FireEtwBulkType
-#endif // FireEtwBulkType
-
 #endif // FEATURE_EVENT_TRACE 
 
 /**************************/
index a334d8a..bacf034 100644 (file)
@@ -75,6 +75,8 @@ stdprolog_cmake="""
 #******************************************************************
 """
 
+specialCaseSizes = { "BulkType" : { "Values" : "Values_ElementSize" }, "GCBulkRootCCW" : { "Values" : "Values_ElementSize" }, "GCBulkRCW" : { "Values" : "Values_ElementSize" }, "GCBulkRootStaticVar" : { "Values" : "Values_ElementSize" } }
+
 lttngDataTypeMapping ={
         #constructed types
         "win:null"          :" ",
@@ -361,17 +363,24 @@ def generateMethodBody(template, providerName, eventName):
     bool success = true;
 """ % (template.estimated_size, template.estimated_size)
         footer = """
-       if (!fixedBuffer)
-               delete[] buffer;
+    if (!fixedBuffer)
+        delete[] buffer;
 """
+
         pack_list = []
         for paramName in fnSig.paramlist:
             parameter = fnSig.getParam(paramName)
 
             if paramName in template.structs:
-                pack_list.append("    success &= WriteToBuffer((const BYTE *)%s, (int)%s_ElementSize * (int)%s, buffer, offset, size, fixedBuffer);" % (paramName, paramName, parameter.prop))
+                size = "(int)%s_ElementSize * (int)%s" % (paramName, parameter.prop)
+                if template.name in specialCaseSizes and paramName in specialCaseSizes[template.name]:
+                    size = "(int)(%s)" % specialCaseSizes[template.name][paramName]
+                pack_list.append("    success &= WriteToBuffer((const BYTE *)%s, %s, buffer, offset, size, fixedBuffer);" % (paramName, size))
             elif paramName in template.arrays:
-                pack_list.append("    success &= WriteToBuffer((const BYTE *)%s, sizeof(%s) * (int)%s, buffer, offset, size, fixedBuffer);" % (paramName, lttngDataTypeMapping[parameter.winType], parameter.prop))
+                size = "sizeof(%s) * (int)%s" % (lttngDataTypeMapping[parameter.winType], parameter.prop)
+                if template.name in specialCaseSizes and paramName in specialCaseSizes[template.name]:
+                    size = "(int)(%s)" % specialCaseSizes[template.name][paramName]
+                pack_list.append("    success &= WriteToBuffer((const BYTE *)%s, %s, buffer, offset, size, fixedBuffer);" % (paramName, size))
             elif parameter.winType == "win:GUID":
                 pack_list.append("    success &= WriteToBuffer(*%s, buffer, offset, size, fixedBuffer);" % (parameter.name,))
             else:
@@ -753,4 +762,4 @@ def main(argv):
 
 if __name__ == '__main__':
     return_code = main(sys.argv[1:])
-    sys.exit(return_code)
+    sys.exit(return_code)
\ No newline at end of file
index 2708829..d8702a5 100644 (file)
@@ -1205,11 +1205,12 @@ void BulkComLogger::FlushRcw()
     EventDataDescCreate(&eventData[2], m_etwRcwData, sizeof(EventRCWEntry) * m_currRcw);
 
     ULONG result = EventWrite(Microsoft_Windows_DotNETRuntimeHandle, &GCBulkRCW, _countof(eventData), eventData);
-    _ASSERTE(result == ERROR_SUCCESS);
 #else
-// UNIXTODO: "Eventing Not Implemented"
+    ULONG result = FireEtXplatGCBulkRCW(m_currRcw, instance, sizeof(EventRCWEntry) * m_currRcw, m_etwRcwData);
 #endif // !defined(FEATURE_PAL)
 
+    _ASSERTE(result == ERROR_SUCCESS);
+
     m_currRcw = 0;
 }
 
@@ -1293,11 +1294,11 @@ void BulkComLogger::FlushCcw()
     EventDataDescCreate(&eventData[2], m_etwCcwData, sizeof(EventCCWEntry) * m_currCcw);
 
     ULONG result = EventWrite(Microsoft_Windows_DotNETRuntimeHandle, &GCBulkRootCCW, _countof(eventData), eventData);
-    _ASSERTE(result == ERROR_SUCCESS);
 #else
-// UNIXTODO: "Eventing Not Implemented"
+    ULONG result = FireEtXplatGCBulkRootCCW(m_currCcw, instance, sizeof(EventCCWEntry) * m_currCcw, m_etwCcwData);
 #endif //!defined(FEATURE_PAL)
 
+    _ASSERTE(result == ERROR_SUCCESS);
 
     m_currCcw = 0;
 }
@@ -1497,11 +1498,12 @@ void BulkStaticsLogger::FireBulkStaticsEvent()
     EventDataDescCreate(&eventData[3], m_buffer, m_used);
 
     ULONG result = EventWrite(Microsoft_Windows_DotNETRuntimeHandle, &GCBulkRootStaticVar, _countof(eventData), eventData);
-    _ASSERTE(result == ERROR_SUCCESS);
 #else
-// UNIXTODO: "Eventing Not Implemented"
+    ULONG result = FireEtXplatGCBulkRootStaticVar(m_count, appDomain, instance, m_used, m_buffer);
 #endif //!defined(FEATURE_PAL)
 
+    _ASSERTE(result == ERROR_SUCCESS);
+
     m_used = 0;
     m_count = 0;
 }
@@ -1700,7 +1702,6 @@ void BulkTypeValue::Clear()
 //
 //
 
-#if !defined(FEATURE_PAL)
 void BulkTypeEventLogger::FireBulkTypeEvent()
 {
     LIMITED_METHOD_CONTRACT;
@@ -1710,7 +1711,10 @@ void BulkTypeEventLogger::FireBulkTypeEvent()
         // No types were batched up, so nothing to send
         return;
     }
+    
+    UINT16 nClrInstanceID = GetClrInstanceId();
 
+#if !defined(FEATURE_PAL)
     // Normally, we'd use the MC-generated FireEtwBulkType for all this gunk, but
     // it's insufficient as the bulk type event is too complex (arrays of structs of
     // varying size). So we directly log the event via EventDataDescCreate and
@@ -1722,7 +1726,6 @@ void BulkTypeEventLogger::FireBulkTypeEvent()
     // before the 64K event size limit, and we already limit our batch size
     // (m_nBulkTypeValueCount) to stay within the 128 descriptor limit.
     EVENT_DATA_DESCRIPTOR EventData[128];
-    UINT16 nClrInstanceID = GetClrInstanceId();
 
     UINT iDesc = 0;
 
@@ -1783,18 +1786,62 @@ void BulkTypeEventLogger::FireBulkTypeEvent()
     }
 
     Win32EventWrite(Microsoft_Windows_DotNETRuntimeHandle, &BulkType, iDesc, EventData);
+    
+#else // FEATURE_PAL
+
+    UINT iSize = 0;
+    
+    for (int iTypeData = 0; iTypeData < m_nBulkTypeValueCount; iTypeData++)
+    {
+        BulkTypeValue& target = m_rgBulkTypeValues[iTypeData];
+        
+        // Do fixed-size data as one bulk copy
+        memcpy(
+                m_BulkTypeEventBuffer + iSize,
+                &(target.fixedSizedData),
+                sizeof(target.fixedSizedData));
+        iSize += sizeof(target.fixedSizedData);
+
+        // Do var-sized data individually per field
+
+        LPCWSTR wszName = target.sName.GetUnicode();
+        if (wszName == NULL)
+        {
+            m_BulkTypeEventBuffer[iSize++] = 0;
+            m_BulkTypeEventBuffer[iSize++] = 0;
+        }
+        else
+        {
+            UINT nameSize = (target.sName.GetCount() + 1) * sizeof(WCHAR);
+            memcpy(m_BulkTypeEventBuffer + iSize, wszName, nameSize);
+            iSize += nameSize;
+        }
+
+        // Type parameter count
+        ULONG params = target.rgTypeParameters.GetCount();
+        
+        ULONG *ptrInt = (ULONG*)(m_BulkTypeEventBuffer + iSize);
+        *ptrInt = params;
+        iSize += 4;
+        
+        target.cTypeParameters = params;
+
+        // Type parameter array
+        if (target.cTypeParameters > 0)
+        {
+            memcpy(m_BulkTypeEventBuffer + iSize, target.rgTypeParameters.GetElements(), sizeof(ULONGLONG) * target.cTypeParameters);
+            iSize += sizeof(ULONGLONG) * target.cTypeParameters;
+        }
+    }
 
+    FireEtwBulkType(m_nBulkTypeValueCount, GetClrInstanceId(), iSize, m_BulkTypeEventBuffer);
+
+#endif // FEATURE_PAL
     // Reset state
     m_nBulkTypeValueCount = 0;
     m_nBulkTypeValueByteCount = 0;
 }
 
-#else
-void BulkTypeEventLogger::FireBulkTypeEvent()
-{
-// UNIXTODO: "Eventing Not Implemented"
-}
-#endif //!defined(FEATURE_PAL)
 #ifndef FEATURE_REDHAWK
 
 //---------------------------------------------------------------------------------------
@@ -4225,7 +4272,6 @@ Return Value:
 
 --*/
 
-#if !defined(FEATURE_PAL)
 void InitializeEventTracing()
 {
     CONTRACTL
@@ -4242,6 +4288,7 @@ void InitializeEventTracing()
     if (FAILED(hr))
         return;
 
+#if !defined(FEATURE_PAL)
     // Register CLR providers with the OS
     if (g_pEtwTracer == NULL)
     {
@@ -4249,6 +4296,7 @@ void InitializeEventTracing()
         if (tempEtwTracer != NULL && tempEtwTracer->Register () == ERROR_SUCCESS)
             g_pEtwTracer = tempEtwTracer.Extract ();
     }
+#endif
 
     g_nClrInstanceId = GetRuntimeId() & 0x0000FFFF; // This will give us duplicate ClrInstanceId after UINT16_MAX
 
@@ -4256,6 +4304,8 @@ void InitializeEventTracing()
     // providers can do so now
     ETW::TypeSystemLog::PostRegistrationInit();
 }
+
+#if !defined(FEATURE_PAL)
 HRESULT ETW::CEtwTracer::Register()
 {
     WRAPPER_NO_CONTRACT;
@@ -4413,9 +4463,9 @@ extern "C"
         PMCGEN_TRACE_CONTEXT context = (PMCGEN_TRACE_CONTEXT)CallbackContext;
 
         BOOLEAN bIsPublicTraceHandle = (context->RegistrationHandle==Microsoft_Windows_DotNETRuntimeHandle);
-        
+
         BOOLEAN bIsPrivateTraceHandle = (context->RegistrationHandle==Microsoft_Windows_DotNETRuntimePrivateHandle);
-        
+
         BOOLEAN bIsRundownTraceHandle = (context->RegistrationHandle==Microsoft_Windows_DotNETRuntimeRundownHandle);
 
 
@@ -4502,13 +4552,9 @@ extern "C"
 
     }
 }
-#else
-
-void InitializeEventTracing(){}
-
-#endif // !defined(FEATURE_PAL)
 #endif // FEATURE_REDHAWK
 
+#endif // FEATURE_PAL
 #ifndef FEATURE_REDHAWK
 
 /****************************************************************************/
@@ -5013,6 +5059,7 @@ VOID ETW::InfoLog::RuntimeInformation(INT32 type)
 
 VOID ETW::CodeSymbolLog::EmitCodeSymbols(Module* pModule)
 {
+#if  !defined(FEATURE_PAL) //UNIXTODO: Enable EmitCodeSymbols
     CONTRACTL {
         NOTHROW;
         GC_NOTRIGGER;
@@ -5042,15 +5089,14 @@ VOID ETW::CodeSymbolLog::EmitCodeSymbols(Module* pModule)
                     // estmate. 
                     static const DWORD maxDataSize = 63000;
 
-                    DWORD quot = length / maxDataSize;
-                    
+                    ldiv_t qr = ldiv(length, maxDataSize);
+
                     // We do not allow pdbs of size greater than 2GB for now, 
                     // so totalChunks should fit in 16 bits.
-                    if (quot < UINT16_MAX)
+                    if (qr.quot < UINT16_MAX)
                     {
                         // If there are trailing bits in the last chunk, then increment totalChunks by 1
-                        DWORD rem = length % maxDataSize;
-                        UINT16 totalChunks = (UINT16)(quot + ((rem != 0) ? 1 : 0));
+                        UINT16 totalChunks = (UINT16)(qr.quot + ((qr.rem != 0) ? 1 : 0));
                         NewArrayHolder<BYTE> chunk(new BYTE[maxDataSize]);
                         DWORD offset = 0;
                         for (UINT16 chunkNum = 0; offset < length; chunkNum++)
@@ -5071,6 +5117,7 @@ VOID ETW::CodeSymbolLog::EmitCodeSymbols(Module* pModule)
             }
         }
     } EX_CATCH{} EX_END_CATCH(SwallowAllExceptions);
+#endif//  !defined(FEATURE_PAL)
 }
 
 /* Returns the length of an in-memory symbol stream
index 50886e4..0932225 100644 (file)
@@ -291,6 +291,10 @@ private:
     // List of types we've batched.
     BulkTypeValue m_rgBulkTypeValues[kMaxCountTypeValues];
 
+#ifdef FEATURE_PAL
+    BYTE m_BulkTypeEventBuffer[65536];
+#endif
+
 #ifdef FEATURE_REDHAWK
     int LogSingleType(EEType * pEEType);
 #else
index 727b573..5fe0b48 100644 (file)
 
 BOOL FinalizerThread::fRunFinalizersOnUnload = FALSE;
 BOOL FinalizerThread::fQuitFinalizer = FALSE;
+
+#if defined(__linux__)
+#define LINUX_HEAP_DUMP_TIME_OUT 10000
+
+extern bool s_forcedGCInProgress;
+ULONGLONG FinalizerThread::LastHeapDumpTime = 0;
+
+Volatile<BOOL> g_TriggerHeapDump = FALSE;
+#endif // __linux__
+
 AppDomain * FinalizerThread::UnloadingAppDomain;
 
 CLREvent * FinalizerThread::hEventFinalizer = NULL;
@@ -509,7 +519,11 @@ void FinalizerThread::WaitForFinalizerEvent (CLREvent *event)
                 cEventsForWait,                           // # objects to wait on
                 &(MHandles[uiEventIndexOffsetForWait]),   // array of objects to wait on
                 FALSE,          // bWaitAll == FALSE, so wait for first signal
+#if defined(__linux__)
+                LINUX_HEAP_DUMP_TIME_OUT,
+#else
                 INFINITE,       // timeout
+#endif
                 FALSE)          // alertable
                 
                 // Adjust the returned array index for the offset we used, so the return
@@ -539,7 +553,17 @@ void FinalizerThread::WaitForFinalizerEvent (CLREvent *event)
                 // Spawn thread to perform the profiler attach, then resume our wait
                 ProfilingAPIAttachDetach::ProcessSignaledAttachEvent();
                 break;
-#endif // FEATURE_PROFAPI_ATTACH_DETACH 
+#endif // FEATURE_PROFAPI_ATTACH_DETACH
+#if defined(__linux__)
+            case (WAIT_TIMEOUT + kLowMemoryNotification):
+            case (WAIT_TIMEOUT + kFinalizer):
+                if (g_TriggerHeapDump)
+                {
+                    return;
+                }
+                
+                break;
+#endif
             default:
                 //what's wrong?
                 _ASSERTE (!"Bad return code from WaitForMultipleObjects");
@@ -550,7 +574,11 @@ void FinalizerThread::WaitForFinalizerEvent (CLREvent *event)
     else {
         static LONG sLastLowMemoryFromHost = 0;
         while (1) {
+#if defined(__linux__)
+            DWORD timeout = LINUX_HEAP_DUMP_TIME_OUT;
+#else
             DWORD timeout = INFINITE;
+#endif
             if (!CLRMemoryHosted())
             {
                 if (WaitForSingleObject(MHandles[kLowMemoryNotification], 0) == WAIT_OBJECT_0) {
@@ -585,6 +613,12 @@ void FinalizerThread::WaitForFinalizerEvent (CLREvent *event)
             case (WAIT_ABANDONED):
                 return;
             case (WAIT_TIMEOUT):
+#if defined(__linux__)
+                if (g_TriggerHeapDump)
+                {
+                    return;
+                }
+#endif
                 break;
             }
         }
@@ -638,6 +672,20 @@ VOID FinalizerThread::FinalizerThreadWorker(void *args)
 
         WaitForFinalizerEvent (hEventFinalizer);
 
+#if defined(__linux__)
+        if (g_TriggerHeapDump && (CLRGetTickCount64() > (LastHeapDumpTime + LINUX_HEAP_DUMP_TIME_OUT)))
+        {
+            s_forcedGCInProgress = true;
+            GetFinalizerThread()->DisablePreemptiveGC();
+            GCHeap::GetGCHeap()->GarbageCollect(2, FALSE, collection_blocking);
+            GetFinalizerThread()->EnablePreemptiveGC();
+            s_forcedGCInProgress = false;
+            
+            LastHeapDumpTime = CLRGetTickCount64();
+            g_TriggerHeapDump = FALSE;
+        }
+#endif
+
         if (!bPriorityBoosted)
         {
             if (GetFinalizerThread()->SetThreadPriority(THREAD_PRIORITY_HIGHEST))
index 2d15e60..c3b6e71 100644 (file)
@@ -11,6 +11,10 @@ class FinalizerThread
     static BOOL fRunFinalizersOnUnload;
     static BOOL fQuitFinalizer;
     static AppDomain *UnloadingAppDomain;
+    
+#if defined(__linux__)
+    static ULONGLONG LastHeapDumpTime;
+#endif
 
     static CLREvent *hEventFinalizer;
     static CLREvent *hEventFinalizerDone;
index 0dfe71d..1b51c47 100644 (file)
@@ -605,6 +605,10 @@ extern ULONGLONG g_ObjFinalizeStartTime;
 extern Volatile<BOOL> g_FinalizerIsRunning;
 extern Volatile<ULONG> g_FinalizerLoopCount;
 
+#ifdef FEATURE_PAL
+extern Volatile<BOOL> g_TriggerHeapDump;
+#endif // FEATURE_PAL
+
 extern LONG GetProcessedExitProcessEventCount();
 
 #ifndef DACCESS_COMPILE