246 lines
8.0 KiB
C#
246 lines
8.0 KiB
C#
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
// File: MemoryDiagnosis.cs
|
||
|
//
|
||
|
//
|
||
|
|
||
|
using System;
|
||
|
using System.Threading;
|
||
|
using System.Runtime.CompilerServices;
|
||
|
|
||
|
using Microsoft.Singularity;
|
||
|
using Microsoft.Singularity.V1.Services;
|
||
|
using Microsoft.Singularity.Eventing;
|
||
|
using System.Collections;
|
||
|
|
||
|
namespace Microsoft.Singularity.Eventing
|
||
|
{
|
||
|
|
||
|
[CLSCompliant(false)]
|
||
|
public class SystemAllocationLogger : EventSource {
|
||
|
|
||
|
private const uint DefaultLogSize = 0x10000;
|
||
|
|
||
|
public static SystemAllocationLogger Create(string sourceName) {
|
||
|
|
||
|
EventingStorage storage = EventingStorage.CreateLocalStorage(QualityOfService.RecyclableEvents,
|
||
|
DefaultLogSize);
|
||
|
|
||
|
if (storage == null) {
|
||
|
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
SystemAllocationLogger Logger = new SystemAllocationLogger(sourceName,
|
||
|
storage,
|
||
|
ENABLE_ALL_MASK);
|
||
|
|
||
|
if (Logger != null) {
|
||
|
|
||
|
Logger.Register();
|
||
|
}
|
||
|
|
||
|
return Logger;
|
||
|
}
|
||
|
|
||
|
|
||
|
//[EventType=Interrupt]
|
||
|
[NoHeapAllocation]
|
||
|
public bool Log(ushort processTag, ushort memoryType, UIntPtr address, UIntPtr size) { // !!!!! this line must be entered to define a schema
|
||
|
|
||
|
|
||
|
if ((ControlFlags & MemoryAllocation_Control_flag) != 0) {
|
||
|
|
||
|
unsafe {
|
||
|
|
||
|
MemoryAllocationEvent memEvent;
|
||
|
|
||
|
memEvent.MemoryType = memoryType;
|
||
|
memEvent.ProcessTag = processTag;
|
||
|
memEvent.Address = address;
|
||
|
memEvent.Size = size;
|
||
|
|
||
|
return (LogEntry(ControlFlags,
|
||
|
eventTypeMemoryAllocation,
|
||
|
(byte *)&memEvent,
|
||
|
sizeof(MemoryAllocationEvent)) != 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
public unsafe struct MemoryAllocationEvent {
|
||
|
|
||
|
public UIntPtr Address;
|
||
|
public UIntPtr Size;
|
||
|
public ushort ProcessTag;
|
||
|
public ushort MemoryType;
|
||
|
};
|
||
|
|
||
|
UIntPtr eventTypeMemoryAllocation;
|
||
|
const uint MemoryAllocation_Control_flag = 0x10000;
|
||
|
|
||
|
public override bool Register() {
|
||
|
|
||
|
if (!base.Register()) {
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (HostController.RegisterEvent("SystemMemoryAllocation",
|
||
|
"Memory allocation event: Address={0}, Memory type = {3}",
|
||
|
ref eventTypeMemoryAllocation)) {
|
||
|
|
||
|
HostController.RegisterEventField(eventTypeMemoryAllocation,
|
||
|
"Address",
|
||
|
0,
|
||
|
DataType.__UIntPtr);
|
||
|
|
||
|
HostController.RegisterEventField(eventTypeMemoryAllocation,
|
||
|
"Size",
|
||
|
0,
|
||
|
DataType.__UIntPtr);
|
||
|
|
||
|
HostController.RegisterEventField(eventTypeMemoryAllocation,
|
||
|
"ProcessTag",
|
||
|
0,
|
||
|
DataType.__uint16);
|
||
|
|
||
|
HostController.RegisterEventField(eventTypeMemoryAllocation,
|
||
|
"MemoryType",
|
||
|
0,
|
||
|
DataType.__uint16);
|
||
|
|
||
|
} else {
|
||
|
|
||
|
// The event might have been registered already
|
||
|
// Check whether we foundit already in the table or not
|
||
|
|
||
|
if (eventTypeMemoryAllocation == 0) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
SystemAllocationLogger (string sourceName, EventingStorage storage, uint controlFlags)
|
||
|
:base(sourceName, storage, controlFlags) {}
|
||
|
|
||
|
}
|
||
|
|
||
|
[CLSCompliant(false)]
|
||
|
[NoCCtor]
|
||
|
public class FreeMemoryDistribution : ActiveSource{
|
||
|
|
||
|
// Empty function declaration. Active counters are never logged through functions
|
||
|
// Present here for further usage with Phoenix codegen
|
||
|
// [ActiveCounter]
|
||
|
void TraceFreeBlock(UIntPtr BlockCount, UIntPtr TotalBlocksSize){}
|
||
|
|
||
|
// Here should start the codegen's work. Do it by hand for now
|
||
|
|
||
|
public struct tmpFreeBlockEntry{
|
||
|
|
||
|
public UIntPtr BlockCount;
|
||
|
public UIntPtr TotalBucketSize;
|
||
|
}
|
||
|
|
||
|
internal tmpFreeBlockEntry[] Buffer;
|
||
|
|
||
|
public static FreeMemoryDistribution Create(string sourceName, int size) {
|
||
|
|
||
|
FreeMemoryDistribution Logger = new FreeMemoryDistribution(sourceName, size, ENABLE_ALL_MASK);
|
||
|
|
||
|
if (Logger != null) {
|
||
|
|
||
|
Logger.Register();
|
||
|
}
|
||
|
|
||
|
return Logger;
|
||
|
}
|
||
|
|
||
|
public override bool Register() {
|
||
|
|
||
|
Buffer = new tmpFreeBlockEntry[Count];
|
||
|
|
||
|
if (Buffer == null) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (HostController.RegisterEvent("MemoryFreeBucket",
|
||
|
"Memory free buckets: Count = {0}",
|
||
|
ref EventTypeHandle)) {
|
||
|
|
||
|
HostController.RegisterEventField(EventTypeHandle,
|
||
|
"BlockCount",
|
||
|
0,
|
||
|
DataType.__UIntPtr);
|
||
|
|
||
|
HostController.RegisterEventField(EventTypeHandle,
|
||
|
"TotalBucketSize",
|
||
|
0,
|
||
|
DataType.__UIntPtr);
|
||
|
} else {
|
||
|
|
||
|
// The event might have been registered already
|
||
|
// Check whether we foundit already in the table or not
|
||
|
|
||
|
if (EventTypeHandle == 0) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
unsafe {
|
||
|
|
||
|
fixed (void * ptr = &Buffer[0]) {
|
||
|
|
||
|
DebugBufferAddress = (UIntPtr)ptr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// After all internal fields are setup, we can go ahead and register with the controller
|
||
|
|
||
|
if (!base.Register()) {
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public tmpFreeBlockEntry this[int index]
|
||
|
{
|
||
|
get {
|
||
|
return Buffer[index];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override unsafe bool GetActiveEntry(int index,
|
||
|
UIntPtr * type,
|
||
|
byte * buffer,
|
||
|
UInt16 bufferSize )
|
||
|
{
|
||
|
if (!base.GetActiveEntry(index, type, buffer, bufferSize)) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
*(tmpFreeBlockEntry *)buffer = Buffer[index];
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
FreeMemoryDistribution(string sourceName, int size, uint controlFlags)
|
||
|
:base(sourceName, size, controlFlags)
|
||
|
{
|
||
|
unsafe {
|
||
|
EntrySize = (ushort)sizeof(tmpFreeBlockEntry);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|