@@ -1804,6 +1804,15 @@ static struct scx_dispatch_q *find_dsq_for_dispatch(struct rq *rq, u64 dsq_id,
1804
1804
if (dsq_id == SCX_DSQ_LOCAL )
1805
1805
return & rq -> scx .local_dsq ;
1806
1806
1807
+ if ((dsq_id & SCX_DSQ_LOCAL_ON ) == SCX_DSQ_LOCAL_ON ) {
1808
+ s32 cpu = dsq_id & SCX_DSQ_LOCAL_CPU_MASK ;
1809
+
1810
+ if (!ops_cpu_valid (cpu , "in SCX_DSQ_LOCAL_ON dispatch verdict" ))
1811
+ return & scx_dsq_global ;
1812
+
1813
+ return & cpu_rq (cpu )-> scx .local_dsq ;
1814
+ }
1815
+
1807
1816
dsq = find_non_local_dsq (dsq_id );
1808
1817
if (unlikely (!dsq )) {
1809
1818
scx_ops_error ("non-existent DSQ 0x%llx for %s[%d]" ,
@@ -1847,8 +1856,8 @@ static void mark_direct_dispatch(struct task_struct *ddsp_task,
1847
1856
static void direct_dispatch (struct task_struct * p , u64 enq_flags )
1848
1857
{
1849
1858
struct rq * rq = task_rq (p );
1850
- struct scx_dispatch_q * dsq ;
1851
- u64 dsq_id = p -> scx .ddsp_dsq_id ;
1859
+ struct scx_dispatch_q * dsq =
1860
+ find_dsq_for_dispatch ( rq , p -> scx .ddsp_dsq_id , p ) ;
1852
1861
1853
1862
touch_core_sched_dispatch (rq , p );
1854
1863
@@ -1860,15 +1869,9 @@ static void direct_dispatch(struct task_struct *p, u64 enq_flags)
1860
1869
* DSQ_LOCAL_ON verdicts targeting the local DSQ of a remote CPU, defer
1861
1870
* the enqueue so that it's executed when @rq can be unlocked.
1862
1871
*/
1863
- if ((dsq_id & SCX_DSQ_LOCAL_ON ) == SCX_DSQ_LOCAL_ON ) {
1864
- s32 cpu = dsq_id & SCX_DSQ_LOCAL_CPU_MASK ;
1872
+ if (dsq -> id == SCX_DSQ_LOCAL && dsq != & rq -> scx .local_dsq ) {
1865
1873
unsigned long opss ;
1866
1874
1867
- if (cpu == cpu_of (rq )) {
1868
- dsq_id = SCX_DSQ_LOCAL ;
1869
- goto dispatch ;
1870
- }
1871
-
1872
1875
opss = atomic_long_read (& p -> scx .ops_state ) & SCX_OPSS_STATE_MASK ;
1873
1876
1874
1877
switch (opss & SCX_OPSS_STATE_MASK ) {
@@ -1895,8 +1898,6 @@ static void direct_dispatch(struct task_struct *p, u64 enq_flags)
1895
1898
return ;
1896
1899
}
1897
1900
1898
- dispatch :
1899
- dsq = find_dsq_for_dispatch (rq , dsq_id , p );
1900
1901
dispatch_enqueue (dsq , p , p -> scx .ddsp_enq_flags | SCX_ENQ_CLEAR_OPSS );
1901
1902
}
1902
1903
@@ -2372,51 +2373,38 @@ static bool consume_dispatch_q(struct rq *rq, struct scx_dispatch_q *dsq)
2372
2373
enum dispatch_to_local_dsq_ret {
2373
2374
DTL_DISPATCHED , /* successfully dispatched */
2374
2375
DTL_LOST , /* lost race to dequeue */
2375
- DTL_NOT_LOCAL , /* destination is not a local DSQ */
2376
2376
DTL_INVALID , /* invalid local dsq_id */
2377
2377
};
2378
2378
2379
2379
/**
2380
2380
* dispatch_to_local_dsq - Dispatch a task to a local dsq
2381
2381
* @rq: current rq which is locked
2382
- * @dsq_id : destination dsq ID
2382
+ * @dst_dsq : destination DSQ
2383
2383
* @p: task to dispatch
2384
2384
* @enq_flags: %SCX_ENQ_*
2385
2385
*
2386
- * We're holding @rq lock and want to dispatch @p to the local DSQ identified by
2387
- * @dsq_id . This function performs all the synchronization dancing needed
2388
- * because local DSQs are protected with rq locks.
2386
+ * We're holding @rq lock and want to dispatch @p to @dst_dsq which is a local
2387
+ * DSQ . This function performs all the synchronization dancing needed because
2388
+ * local DSQs are protected with rq locks.
2389
2389
*
2390
2390
* The caller must have exclusive ownership of @p (e.g. through
2391
2391
* %SCX_OPSS_DISPATCHING).
2392
2392
*/
2393
2393
static enum dispatch_to_local_dsq_ret
2394
- dispatch_to_local_dsq (struct rq * rq , u64 dsq_id , struct task_struct * p ,
2395
- u64 enq_flags )
2394
+ dispatch_to_local_dsq (struct rq * rq , struct scx_dispatch_q * dst_dsq ,
2395
+ struct task_struct * p , u64 enq_flags )
2396
2396
{
2397
2397
struct rq * src_rq = task_rq (p );
2398
- struct rq * dst_rq ;
2398
+ struct rq * dst_rq = container_of ( dst_dsq , struct rq , scx . local_dsq ) ;
2399
2399
2400
2400
/*
2401
2401
* We're synchronized against dequeue through DISPATCHING. As @p can't
2402
2402
* be dequeued, its task_rq and cpus_allowed are stable too.
2403
+ *
2404
+ * If dispatching to @rq that @p is already on, no lock dancing needed.
2403
2405
*/
2404
- if (dsq_id == SCX_DSQ_LOCAL ) {
2405
- dst_rq = rq ;
2406
- } else if ((dsq_id & SCX_DSQ_LOCAL_ON ) == SCX_DSQ_LOCAL_ON ) {
2407
- s32 cpu = dsq_id & SCX_DSQ_LOCAL_CPU_MASK ;
2408
-
2409
- if (!ops_cpu_valid (cpu , "in SCX_DSQ_LOCAL_ON dispatch verdict" ))
2410
- return DTL_INVALID ;
2411
- dst_rq = cpu_rq (cpu );
2412
- } else {
2413
- return DTL_NOT_LOCAL ;
2414
- }
2415
-
2416
- /* if dispatching to @rq that @p is already on, no lock dancing needed */
2417
2406
if (rq == src_rq && rq == dst_rq ) {
2418
- dispatch_enqueue (& dst_rq -> scx .local_dsq , p ,
2419
- enq_flags | SCX_ENQ_CLEAR_OPSS );
2407
+ dispatch_enqueue (dst_dsq , p , enq_flags | SCX_ENQ_CLEAR_OPSS );
2420
2408
return DTL_DISPATCHED ;
2421
2409
}
2422
2410
@@ -2558,19 +2546,21 @@ static void finish_dispatch(struct rq *rq, struct task_struct *p,
2558
2546
2559
2547
BUG_ON (!(p -> scx .flags & SCX_TASK_QUEUED ));
2560
2548
2561
- switch (dispatch_to_local_dsq (rq , dsq_id , p , enq_flags )) {
2562
- case DTL_DISPATCHED :
2563
- break ;
2564
- case DTL_LOST :
2565
- break ;
2566
- case DTL_INVALID :
2567
- dsq_id = SCX_DSQ_GLOBAL ;
2568
- fallthrough ;
2569
- case DTL_NOT_LOCAL :
2570
- dsq = find_dsq_for_dispatch (cpu_rq (raw_smp_processor_id ()),
2571
- dsq_id , p );
2549
+ dsq = find_dsq_for_dispatch (this_rq (), dsq_id , p );
2550
+
2551
+ if (dsq -> id == SCX_DSQ_LOCAL ) {
2552
+ switch (dispatch_to_local_dsq (rq , dsq , p , enq_flags )) {
2553
+ case DTL_DISPATCHED :
2554
+ break ;
2555
+ case DTL_LOST :
2556
+ break ;
2557
+ case DTL_INVALID :
2558
+ dispatch_enqueue (& scx_dsq_global , p ,
2559
+ enq_flags | SCX_ENQ_CLEAR_OPSS );
2560
+ break ;
2561
+ }
2562
+ } else {
2572
2563
dispatch_enqueue (dsq , p , enq_flags | SCX_ENQ_CLEAR_OPSS );
2573
- break ;
2574
2564
}
2575
2565
}
2576
2566
@@ -2747,13 +2737,13 @@ static void process_ddsp_deferred_locals(struct rq *rq)
2747
2737
*/
2748
2738
while ((p = list_first_entry_or_null (& rq -> scx .ddsp_deferred_locals ,
2749
2739
struct task_struct , scx .dsq_list .node ))) {
2750
- s32 ret ;
2740
+ struct scx_dispatch_q * dsq ;
2751
2741
2752
2742
list_del_init (& p -> scx .dsq_list .node );
2753
2743
2754
- ret = dispatch_to_local_dsq (rq , p -> scx .ddsp_dsq_id , p ,
2755
- p -> scx . ddsp_enq_flags );
2756
- WARN_ON_ONCE ( ret == DTL_NOT_LOCAL );
2744
+ dsq = find_dsq_for_dispatch (rq , p -> scx .ddsp_dsq_id , p );
2745
+ if (! WARN_ON_ONCE ( dsq -> id != SCX_DSQ_LOCAL ))
2746
+ dispatch_to_local_dsq ( rq , dsq , p , p -> scx . ddsp_enq_flags );
2757
2747
}
2758
2748
}
2759
2749
0 commit comments