@@ -46,16 +46,20 @@ public void StartOboeBridge(Scheduler scheduler, Action<double> onLatencyMeasure
4646 if ( provider != IntPtr . Zero )
4747 bridge . SetProvider ( provider ) ;
4848
49- // Calculate dynamic big-core mask for audio thread, matching the pattern in OsuGameAndroid.LoadComplete
50- int audioAffinityMask ;
51- int cores = System . Environment . ProcessorCount ;
52- int bigStart = Math . Max ( cores / 2 , 1 ) ;
53- audioAffinityMask = 0 ;
49+ // Use sysfs-based CPU topology for smart big-core detection.
50+ // Falls back to generic upper-half heuristic if native library unavailable.
51+ int audioAffinityMask = GetBigCoreMask ( ) ;
5452
55- for ( int i = bigStart ; i < Math . Min ( cores , 32 ) ; i ++ )
56- audioAffinityMask |= 1 << i ;
53+ if ( audioAffinityMask == 0 )
54+ {
55+ int cores = System . Environment . ProcessorCount ;
56+ int bigStart = Math . Max ( cores / 2 , 1 ) ;
57+
58+ for ( int i = bigStart ; i < Math . Min ( cores , 32 ) ; i ++ )
59+ audioAffinityMask |= 1 << i ;
5760
58- if ( audioAffinityMask == 0 ) audioAffinityMask = ( 1 << Math . Min ( cores , 31 ) ) - 1 ;
61+ if ( audioAffinityMask == 0 ) audioAffinityMask = ( 1 << Math . Min ( cores , 31 ) ) - 1 ;
62+ }
5963
6064 try { SetThreadAffinity ( audioAffinityMask ) ; }
6165 catch ( Exception e ) { Debug . WriteLine ( $ "[osu!] Audio thread affinity failed: { e . Message } ") ; }
@@ -114,6 +118,19 @@ public void StopOboeBridge()
114118 [ MethodImpl ( MethodImplOptions . NoInlining ) ]
115119 public static bool SetThreadAffinity ( int coreMask ) => OboeAudioBridge . nSetThreadAffinity ( coreMask ) != 0 ;
116120
121+ /// <summary>
122+ /// Returns a bitmask of high-performance CPU cores detected via sysfs topology.
123+ /// Uses /sys/devices/system/cpu/cpuN/cpufreq/cpuinfo_max_freq to identify cores
124+ /// whose max frequency is >= 70% of the fastest core (Prime + Gold on big.LITTLE SoCs).
125+ /// Returns 0 if sysfs is unavailable; callers should use a fallback heuristic.
126+ /// </summary>
127+ [ MethodImpl ( MethodImplOptions . NoInlining ) ]
128+ public static int GetBigCoreMask ( )
129+ {
130+ try { return OboeAudioBridge . nGetBigCoreMask ( ) ; }
131+ catch { return 0 ; }
132+ }
133+
117134 [ MethodImpl ( MethodImplOptions . NoInlining ) ]
118135 public bool IsOboeActive ( ) => ( oboeBridge as OboeAudioBridge ) ? . IsActive ?? false ;
119136
0 commit comments