@@ -9,31 +9,20 @@ namespace ProcessorLatencyTool.Helpers.LatencyTester;
99[ SupportedOSPlatform ( "osx" ) ]
1010public sealed unsafe partial class MacOsLatencyTester : LatencyTesterBase
1111{
12- // QoS class constants from MacOS
13- private const int QOS_CLASS_USER_INTERACTIVE = 0x21 ;
14- private const int QOS_CLASS_USER_INITIATED = 0x19 ;
15- private const int QOS_CLASS_DEFAULT = 0x15 ;
16- private const int QOS_CLASS_UTILITY = 0x11 ;
17- private const int QOS_CLASS_BACKGROUND = 0x09 ;
18-
19- // Error codes
20- private const int EPERM = 1 ;
21- private const int EINVAL = 22 ;
22-
2312 [ LibraryImport ( "libSystem.dylib" , EntryPoint = "pthread_self" ) ]
2413 private static partial IntPtr pthread_self ( ) ;
2514
26- [ LibraryImport ( "libSystem.dylib" , EntryPoint = "pthread_set_qos_class_self_np" ) ]
27- private static partial int pthread_set_qos_class_self_np ( int qos_class , int relative_priority ) ;
28-
2915 [ LibraryImport ( "libSystem.dylib" , EntryPoint = "pthread_getname_np" ) ]
3016 private static partial int pthread_getname_np ( IntPtr thread , byte * name , nuint len ) ;
3117
3218 [ LibraryImport ( "libSystem.dylib" , EntryPoint = "pthread_setname_np" ) ]
3319 private static partial int pthread_setname_np ( byte * name ) ;
3420
35- [ LibraryImport ( "libSystem.dylib" , EntryPoint = "pthread_get_qos_class_np" ) ]
36- private static partial int pthread_get_qos_class_np ( IntPtr thread , out int qos_class , out int relative_priority ) ;
21+ [ LibraryImport ( "arm64_registers" , EntryPoint = "set_realtime_policy" ) ]
22+ private static partial int set_realtime_policy ( ) ;
23+
24+ [ LibraryImport ( "arm64_registers" , EntryPoint = "get_thread_policy" ) ]
25+ private static partial int get_thread_policy ( out int is_realtime , out int importance ) ;
3726
3827 [ LibraryImport ( "arm64_registers" , EntryPoint = "read_tpidr_el0" ) ]
3928 private static partial ulong ReadTpidrEl0 ( ) ;
@@ -44,69 +33,6 @@ public sealed unsafe partial class MacOsLatencyTester : LatencyTesterBase
4433 [ LibraryImport ( "arm64_registers" , EntryPoint = "read_cntfrq_el0" ) ]
4534 private static partial ulong ReadCntfrqEl0 ( ) ;
4635
47- private string GetQosClassName ( int qosClass )
48- {
49- return qosClass switch
50- {
51- QOS_CLASS_USER_INTERACTIVE => "USER_INTERACTIVE" ,
52- QOS_CLASS_USER_INITIATED => "USER_INITIATED" ,
53- QOS_CLASS_DEFAULT => "DEFAULT" ,
54- QOS_CLASS_UTILITY => "UTILITY" ,
55- QOS_CLASS_BACKGROUND => "BACKGROUND" ,
56- _ => $ "UNKNOWN({ qosClass } )"
57- } ;
58- }
59-
60- private bool SetQosClass ( int qosClass )
61- {
62- var threadId = pthread_self ( ) ;
63- int currentQos ;
64- int currentPriority ;
65-
66- // Get current QoS class
67- var getResult = pthread_get_qos_class_np ( threadId , out currentQos , out currentPriority ) ;
68- if ( getResult == 0 )
69- {
70- Console . WriteLine ( $ "Current QoS class: { GetQosClassName ( currentQos ) } (priority: { currentPriority } )") ;
71- }
72-
73- var result = pthread_set_qos_class_self_np ( qosClass , 0 ) ;
74- if ( result != 0 )
75- {
76- switch ( result )
77- {
78- case EPERM :
79- Console . WriteLine ( $ "Warning: Permission denied setting QoS class to { GetQosClassName ( qosClass ) } . Try running with sudo.") ;
80- break ;
81- case EINVAL :
82- Console . WriteLine ( $ "Warning: Invalid QoS class value { GetQosClassName ( qosClass ) } ") ;
83- break ;
84- default :
85- Console . WriteLine ( $ "Warning: Failed to set QoS class to { GetQosClassName ( qosClass ) } (error { result } )") ;
86- break ;
87- }
88- return false ;
89- }
90-
91- // Verify the change
92- getResult = pthread_get_qos_class_np ( threadId , out currentQos , out currentPriority ) ;
93- if ( getResult == 0 )
94- {
95- if ( currentQos == qosClass )
96- {
97- Console . WriteLine ( $ "Successfully set QoS class to { GetQosClassName ( currentQos ) } ") ;
98- return true ;
99- }
100- else
101- {
102- Console . WriteLine ( $ "Warning: QoS class mismatch. Requested: { GetQosClassName ( qosClass ) } , Current: { GetQosClassName ( currentQos ) } ") ;
103- return false ;
104- }
105- }
106-
107- return true ;
108- }
109-
11036 private void SetThreadName ( string name )
11137 {
11238 // Max thread name length in MacOS is 64 bytes
@@ -127,17 +53,42 @@ protected override void SetThreadAffinity(int core)
12753 // Set thread name for debugging
12854 SetThreadName ( $ "LatencyTest_Core{ core } ") ;
12955
130- // First try to set QoS class to user interactive
131- if ( ! SetQosClass ( QOS_CLASS_USER_INTERACTIVE ) )
56+ // Get current thread policy
57+ int isRealtime , importance ;
58+ var result = get_thread_policy ( out isRealtime , out importance ) ;
59+ if ( result == 0 )
60+ {
61+ Console . WriteLine ( $ "Current thread policy - Realtime: { isRealtime } , Importance: { importance } ") ;
62+ }
63+
64+ // Try to set realtime policy
65+ result = set_realtime_policy ( ) ;
66+ if ( result != 0 )
67+ {
68+ switch ( result )
69+ {
70+ case - 1 :
71+ Console . WriteLine ( "Warning: Could not get thread port" ) ;
72+ break ;
73+ case - 2 :
74+ Console . WriteLine ( "Warning: Could not set extended policy" ) ;
75+ break ;
76+ case - 3 :
77+ Console . WriteLine ( "Warning: Could not set precedence policy" ) ;
78+ break ;
79+ default :
80+ Console . WriteLine ( $ "Warning: Unknown error setting thread policy ({ result } )") ;
81+ break ;
82+ }
83+ Console . WriteLine ( "Warning: Failed to set realtime policy. Performance may be affected." ) ;
84+ }
85+ else
13286 {
133- // If that fails, try user initiated
134- if ( ! SetQosClass ( QOS_CLASS_USER_INITIATED ) )
87+ // Verify the change
88+ result = get_thread_policy ( out isRealtime , out importance ) ;
89+ if ( result == 0 )
13590 {
136- // If that also fails, try default
137- if ( ! SetQosClass ( QOS_CLASS_DEFAULT ) )
138- {
139- Console . WriteLine ( "Warning: Failed to set any QoS class. Performance may be affected." ) ;
140- }
91+ Console . WriteLine ( $ "Thread policy set - Realtime: { isRealtime } , Importance: { importance } ") ;
14192 }
14293 }
14394
@@ -148,8 +99,6 @@ protected override void SetThreadAffinity(int core)
14899 {
149100 pthread_getname_np ( threadId , namePtr , 64 ) ;
150101 }
151-
152- Console . WriteLine ( $ "Info: Thread { threadId } (Core { core } ) set to User Interactive QoS") ;
153102 }
154103 catch ( Exception ex )
155104 {
@@ -180,4 +129,4 @@ protected override double GetTimerPeriodNs()
180129 }
181130 return 1_000_000_000.0 / Stopwatch . Frequency ;
182131 }
183- }
132+ }
0 commit comments