5
5
using System . Diagnostics ;
6
6
using System . Runtime . CompilerServices ;
7
7
using System . Runtime . InteropServices ;
8
- using System . Text ;
9
8
using XenoAtom . Collections ;
10
9
11
10
namespace Ultra . Sampler . MacOS ;
@@ -14,7 +13,7 @@ internal unsafe class MacOSUltraSampler : UltraSampler
14
13
{
15
14
private bool _stopped ;
16
15
private Thread ? _thread ;
17
- private bool _stackCaptureEnabled ;
16
+ private bool _captureEnabled ;
18
17
private readonly AutoResetEvent _resumeCaptureThread ;
19
18
20
19
private const int MaximumFrames = 4096 ;
@@ -69,14 +68,14 @@ protected override void StopImpl()
69
68
protected override void EnableImpl ( )
70
69
{
71
70
_nextModuleEventIndexToLog = 0 ;
72
- _stackCaptureEnabled = true ;
71
+ _captureEnabled = true ;
73
72
_resumeCaptureThread . Set ( ) ;
74
73
}
75
74
76
75
protected override void DisableImpl ( )
77
76
{
78
77
_nextModuleEventIndexToLog = 0 ;
79
- _stackCaptureEnabled = false ;
78
+ _captureEnabled = false ;
80
79
}
81
80
82
81
private unsafe void RunImpl ( )
@@ -91,13 +90,13 @@ private unsafe void RunImpl()
91
90
92
91
while ( ! _stopped )
93
92
{
94
- if ( _stackCaptureEnabled )
93
+ if ( _captureEnabled )
95
94
{
96
95
// Load all pending native module events before sampling
97
- LoadPendingNativeModuleEvents ( ) ;
96
+ NotifyPendingNativeModuleEvents ( ) ;
98
97
99
98
// Sample the callstacks
100
- Sample ( rootTask , currentThreadId , _frames , UltraSamplerSource . Log . Callstack ) ;
99
+ Sample ( rootTask , currentThreadId , _frames , UltraSamplerSource . Log . OnNativeCallstack ) ;
101
100
102
101
// Sleep for 1ms
103
102
Thread . Sleep ( 1 ) ;
@@ -156,15 +155,15 @@ public NativeModuleEvent[] GetNativeModuleEvents()
156
155
}
157
156
}
158
157
159
- private void LoadPendingNativeModuleEvents ( )
158
+ private void NotifyPendingNativeModuleEvents ( )
160
159
{
161
160
lock ( _moduleEventLock )
162
161
{
163
162
var events = _moduleEvents . AsSpan ( ) ;
164
163
for ( ; _nextModuleEventIndexToLog < events . Length ; _nextModuleEventIndexToLog ++ )
165
164
{
166
165
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 ) ;
168
167
}
169
168
}
170
169
}
@@ -191,18 +190,18 @@ private static bool TryGetUuidFromMacHeader(nint headerPtr, out Guid guid)
191
190
return false ;
192
191
}
193
192
194
- public void Sample ( CallstackDelegate callstack )
193
+ public void Sample ( NativeCallstackDelegate nativeCallstack )
195
194
{
196
195
MacOS . MacOSLibSystem . task_for_pid ( MacOS . MacOSLibSystem . mach_task_self ( ) , Process . GetCurrentProcess ( ) . Id , out var rootTask )
197
196
. ThrowIfError ( "task_for_pid" ) ;
198
197
199
198
MacOS . MacOSLibSystem . pthread_threadid_np ( 0 , out var currentThreadId )
200
199
. ThrowIfError ( "pthread_threadid_np" ) ;
201
200
202
- Sample ( rootTask , currentThreadId , _frames , callstack ) ;
201
+ Sample ( rootTask , currentThreadId , _frames , nativeCallstack ) ;
203
202
}
204
203
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 )
206
205
{
207
206
// We support only ARM64 for the sampler
208
207
if ( RuntimeInformation . ProcessArchitecture != Architecture . Arm64 ) return ;
@@ -251,8 +250,8 @@ private static unsafe void Sample(MacOS.MacOSLibSystem.mach_port_t rootTask, ulo
251
250
. ThrowIfError ( "thread_get_state" ) ;
252
251
253
252
//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 ) ;
256
255
}
257
256
finally
258
257
{
@@ -267,7 +266,7 @@ private static unsafe void Sample(MacOS.MacOSLibSystem.mach_port_t rootTask, ulo
267
266
}
268
267
}
269
268
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 )
271
270
{
272
271
// The macOS ARM64 mandates that the frame pointer is always present
273
272
int frameIndex = 0 ;
@@ -281,26 +280,4 @@ private static unsafe int WalkCallStack(ulong sp, ulong fp, ulong lr, ulong* fra
281
280
282
281
return frameIndex ;
283
282
}
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
+ }
0 commit comments