Skip to content

Commit bd538c3

Browse files
committed
Cleanup some code
1 parent 7a457db commit bd538c3

6 files changed

+95
-67
lines changed

src/Ultra.Sampler/MacOS/MacOSUltraSampler.cs

+15-38
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using System.Diagnostics;
66
using System.Runtime.CompilerServices;
77
using System.Runtime.InteropServices;
8-
using System.Text;
98
using XenoAtom.Collections;
109

1110
namespace Ultra.Sampler.MacOS;
@@ -14,7 +13,7 @@ internal unsafe class MacOSUltraSampler : UltraSampler
1413
{
1514
private bool _stopped;
1615
private Thread? _thread;
17-
private bool _stackCaptureEnabled;
16+
private bool _captureEnabled;
1817
private readonly AutoResetEvent _resumeCaptureThread;
1918

2019
private const int MaximumFrames = 4096;
@@ -69,14 +68,14 @@ protected override void StopImpl()
6968
protected override void EnableImpl()
7069
{
7170
_nextModuleEventIndexToLog = 0;
72-
_stackCaptureEnabled = true;
71+
_captureEnabled = true;
7372
_resumeCaptureThread.Set();
7473
}
7574

7675
protected override void DisableImpl()
7776
{
7877
_nextModuleEventIndexToLog = 0;
79-
_stackCaptureEnabled = false;
78+
_captureEnabled = false;
8079
}
8180

8281
private unsafe void RunImpl()
@@ -91,13 +90,13 @@ private unsafe void RunImpl()
9190

9291
while (!_stopped)
9392
{
94-
if (_stackCaptureEnabled)
93+
if (_captureEnabled)
9594
{
9695
// Load all pending native module events before sampling
97-
LoadPendingNativeModuleEvents();
96+
NotifyPendingNativeModuleEvents();
9897

9998
// Sample the callstacks
100-
Sample(rootTask, currentThreadId, _frames, UltraSamplerSource.Log.Callstack);
99+
Sample(rootTask, currentThreadId, _frames, UltraSamplerSource.Log.OnNativeCallstack);
101100

102101
// Sleep for 1ms
103102
Thread.Sleep(1);
@@ -156,15 +155,15 @@ public NativeModuleEvent[] GetNativeModuleEvents()
156155
}
157156
}
158157

159-
private void LoadPendingNativeModuleEvents()
158+
private void NotifyPendingNativeModuleEvents()
160159
{
161160
lock (_moduleEventLock)
162161
{
163162
var events = _moduleEvents.AsSpan();
164163
for(; _nextModuleEventIndexToLog < events.Length; _nextModuleEventIndexToLog++)
165164
{
166165
var evt = events[_nextModuleEventIndexToLog];
167-
UltraSamplerSource.Log.OnNativeModuleEvent((int)evt.Kind, evt.LoadAddress, evt.Path, evt.TimestampUtc);
166+
UltraSamplerSource.Log.OnNativeModuleEvent(evt.Kind, evt.LoadAddress, evt.Path, evt.TimestampUtc.Ticks);
168167
}
169168
}
170169
}
@@ -191,18 +190,18 @@ private static bool TryGetUuidFromMacHeader(nint headerPtr, out Guid guid)
191190
return false;
192191
}
193192

194-
public void Sample(CallstackDelegate callstack)
193+
public void Sample(NativeCallstackDelegate nativeCallstack)
195194
{
196195
MacOS.MacOSLibSystem.task_for_pid(MacOS.MacOSLibSystem.mach_task_self(), Process.GetCurrentProcess().Id, out var rootTask)
197196
.ThrowIfError("task_for_pid");
198197

199198
MacOS.MacOSLibSystem.pthread_threadid_np(0, out var currentThreadId)
200199
.ThrowIfError("pthread_threadid_np");
201200

202-
Sample(rootTask, currentThreadId, _frames, callstack);
201+
Sample(rootTask, currentThreadId, _frames, nativeCallstack);
203202
}
204203

205-
private static unsafe void Sample(MacOS.MacOSLibSystem.mach_port_t rootTask, ulong currentThreadId, Span<ulong> frames, CallstackDelegate callstack)
204+
private static unsafe void Sample(MacOS.MacOSLibSystem.mach_port_t rootTask, ulong currentThreadId, Span<ulong> frames, NativeCallstackDelegate nativeCallstack)
206205
{
207206
// We support only ARM64 for the sampler
208207
if (RuntimeInformation.ProcessArchitecture != Architecture.Arm64) return;
@@ -251,8 +250,8 @@ private static unsafe void Sample(MacOS.MacOSLibSystem.mach_port_t rootTask, ulo
251250
.ThrowIfError("thread_get_state");
252251

253252
//Console.WriteLine($"sp: 0x{armThreadState.__sp:X8}, fp: 0x{armThreadState.__fp:X8}, lr: 0x{armThreadState.__lr:X8}");
254-
int frameCount = WalkCallStack(armThreadState.__sp, armThreadState.__fp, armThreadState.__lr, pFrames);
255-
callstack(threadInfo.thread_id, pFrames, frameCount);
253+
int frameCount = WalkNativeCallStack(armThreadState.__sp, armThreadState.__fp, armThreadState.__lr, pFrames);
254+
nativeCallstack(threadInfo.thread_id, pFrames, frameCount);
256255
}
257256
finally
258257
{
@@ -267,7 +266,7 @@ private static unsafe void Sample(MacOS.MacOSLibSystem.mach_port_t rootTask, ulo
267266
}
268267
}
269268

270-
private static unsafe int WalkCallStack(ulong sp, ulong fp, ulong lr, ulong* frames)
269+
private static unsafe int WalkNativeCallStack(ulong sp, ulong fp, ulong lr, ulong* frames)
271270
{
272271
// The macOS ARM64 mandates that the frame pointer is always present
273272
int frameIndex = 0;
@@ -281,26 +280,4 @@ private static unsafe int WalkCallStack(ulong sp, ulong fp, ulong lr, ulong* fra
281280

282281
return frameIndex;
283282
}
284-
}
285-
286-
public struct NativeModuleEvent
287-
{
288-
public NativeModuleEventKind Kind;
289-
public ulong LoadAddress;
290-
public byte[]? Path;
291-
public DateTime TimestampUtc;
292-
293-
public override string ToString()
294-
{
295-
return $"{nameof(LoadAddress)}: 0x{LoadAddress:X8}, {nameof(Path)}: {Path}, {nameof(TimestampUtc)}: {TimestampUtc:O}";
296-
}
297-
}
298-
299-
public enum NativeModuleEventKind
300-
{
301-
AlreadyLoaded,
302-
Loaded,
303-
Unloaded
304-
}
305-
306-
public unsafe delegate void CallstackDelegate(ulong threadId, ulong* pFrames, int frameCount);
283+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Copyright (c) Alexandre Mutel. All rights reserved.
2+
// Licensed under the BSD-Clause 2 license.
3+
// See license.txt file in the project root for full license information.
4+
5+
namespace Ultra.Sampler.MacOS;
6+
7+
public unsafe delegate void NativeCallstackDelegate(ulong threadId, ulong* pFrames, int frameCount);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright (c) Alexandre Mutel. All rights reserved.
2+
// Licensed under the BSD-Clause 2 license.
3+
// See license.txt file in the project root for full license information.
4+
5+
namespace Ultra.Sampler.MacOS;
6+
7+
internal struct NativeModuleEvent
8+
{
9+
public NativeModuleEventKind Kind;
10+
public ulong LoadAddress;
11+
public byte[]? Path;
12+
public DateTime TimestampUtc;
13+
14+
public override string ToString()
15+
{
16+
return $"{nameof(LoadAddress)}: 0x{LoadAddress:X8}, {nameof(Path)}: {Path}, {nameof(TimestampUtc)}: {TimestampUtc:O}";
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright (c) Alexandre Mutel. All rights reserved.
2+
// Licensed under the BSD-Clause 2 license.
3+
// See license.txt file in the project root for full license information.
4+
5+
namespace Ultra.Sampler.MacOS;
6+
7+
internal enum NativeModuleEventKind
8+
{
9+
AlreadyLoaded = 0,
10+
Loaded = 1,
11+
Unloaded = 2
12+
}

src/Ultra.Sampler/UltraSamplerParser.cs

+19-1
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,27 @@ public static class UltraSamplerParser
1010

1111
public const string IdAsString = "04E4DCBF-494F-4A77-B55E-F5C041A92F56";
1212

13-
public static readonly Guid Id = new(IdAsString);
13+
public static readonly Guid Id = BitConverter.IsLittleEndian ? new([
14+
0xBF, 0xDC, 0xE4, 0x04, // Data1 (reversed)
15+
0x4F, 0x49, // Data2 (reversed)
16+
0x77, 0x4A, // Data3 (reversed)
17+
0xB5, 0x5E, // Data4 (unchanged)
18+
0xF5, 0xC0, 0x41, 0xA9, 0x2F, 0x56 // Data4 (unchanged)
19+
]) : new([
20+
0x04, 0xE4, 0xDC, 0xBF, // Data1
21+
0x49, 0x4F, // Data2
22+
0x4A, 0x77, // Data3
23+
0xB5, 0x5E, // Data4
24+
0xF5, 0xC0, 0x41, 0xA9, 0x2F, 0x56 // Data4
25+
]);
1426

1527
public const int NativeCallStackEvent = 1;
1628

1729
public const int NativeModuleEvent = 2;
30+
31+
32+
public static void TestId(Guid guid)
33+
{
34+
guid = Id;
35+
}
1836
}

src/Ultra.Sampler/UltraSamplerSource.cs

+24-28
Original file line numberDiff line numberDiff line change
@@ -4,52 +4,48 @@
44

55
using System.Diagnostics.Tracing;
66
using System.Runtime.CompilerServices;
7+
using Ultra.Sampler.MacOS;
78

89
namespace Ultra.Sampler;
910

1011
[EventSource(Name = UltraSamplerParser.Name, Guid = UltraSamplerParser.IdAsString)]
11-
public class UltraSamplerSource : EventSource
12+
internal sealed class UltraSamplerSource : EventSource
1213
{
1314
public static readonly UltraSamplerSource Log = new();
1415

1516
private UltraSamplerSource()
1617
{
1718
}
1819

19-
[Event(UltraSamplerParser.NativeCallStackEvent, Level = EventLevel.Verbose, Message = "Thread {0} Callstack")]
20+
[Event(UltraSamplerParser.NativeCallStackEvent, Level = EventLevel.Verbose, Message = "NativeCallstackEvent Thread {0} with {2} frames")]
2021
[SkipLocalsInit]
21-
public unsafe void Callstack(ulong threadId, ulong* pFrames, int count)
22+
public unsafe void OnNativeCallstack(ulong threadId, ulong* pFrames, int count)
2223
{
23-
if (IsEnabled())
24-
{
25-
Unsafe.SkipInit(out EventData2 evt);
26-
evt.Data1.DataPointer = (nint)(void*)&threadId;
27-
evt.Data1.Size = sizeof(ulong);
28-
evt.Data2.DataPointer = (nint)pFrames;
29-
evt.Data2.Size = count * sizeof(ulong);
30-
WriteEventCore(UltraSamplerParser.NativeCallStackEvent, 2, &evt.Data1);
31-
}
24+
25+
Unsafe.SkipInit(out EventData2 evt);
26+
evt.Data1.DataPointer = (nint)(void*)&threadId;
27+
evt.Data1.Size = sizeof(ulong);
28+
evt.Data2.DataPointer = (nint)pFrames;
29+
evt.Data2.Size = count * sizeof(ulong);
30+
WriteEventCore(UltraSamplerParser.NativeCallStackEvent, 2, &evt.Data1);
3231
}
3332

34-
[Event(UltraSamplerParser.NativeModuleEvent, Level = EventLevel.Verbose, Message = "NativeModule {0} Address: {1}")]
33+
[Event(UltraSamplerParser.NativeModuleEvent, Level = EventLevel.Verbose, Message = "NativeModuleEvent {0} LoadAddress: {1}")]
3534
[SkipLocalsInit]
36-
public unsafe void OnNativeModuleEvent(int evtKind, ulong evtLoadAddress, byte[]? evtPath, DateTime evtTimestampUtc)
35+
public unsafe void OnNativeModuleEvent(NativeModuleEventKind nativeModuleEventKind, ulong loadAddress, byte[]? modulePathUtf8, long timestampUtc)
3736
{
38-
if (IsEnabled())
37+
Unsafe.SkipInit(out EventData4 evt);
38+
evt.Data1.DataPointer = (nint)(void*)&nativeModuleEventKind;
39+
evt.Data1.Size = sizeof(int);
40+
evt.Data2.DataPointer = (nint)(void*)&loadAddress;
41+
evt.Data2.Size = sizeof(ulong);
42+
fixed (byte* evtPathPtr = modulePathUtf8)
3943
{
40-
Unsafe.SkipInit(out EventData4 evt);
41-
evt.Data1.DataPointer = (nint)(void*)&evtKind;
42-
evt.Data1.Size = sizeof(int);
43-
evt.Data2.DataPointer = (nint)(void*)&evtLoadAddress;
44-
evt.Data2.Size = sizeof(ulong);
45-
fixed (byte* evtPathPtr = evtPath)
46-
{
47-
evt.Data3.DataPointer = (nint)evtPathPtr;
48-
evt.Data3.Size = evtPath?.Length ?? 0;
49-
evt.Data4.DataPointer = (nint)(void*)&evtTimestampUtc;
50-
evt.Data4.Size = sizeof(DateTime);
51-
WriteEventCore(UltraSamplerParser.NativeModuleEvent, 4, &evt.Data1);
52-
}
44+
evt.Data3.DataPointer = (nint)evtPathPtr;
45+
evt.Data3.Size = modulePathUtf8?.Length ?? 0;
46+
evt.Data4.DataPointer = (nint)(void*)&timestampUtc;
47+
evt.Data4.Size = sizeof(long);
48+
WriteEventCore(UltraSamplerParser.NativeModuleEvent, 4, &evt.Data1);
5349
}
5450
}
5551

0 commit comments

Comments
 (0)