@@ -41,6 +41,13 @@ static bool scx_init_task_enabled;
4141static bool scx_switching_all ;
4242DEFINE_STATIC_KEY_FALSE (__scx_switched_all );
4343
44+ /*
45+ * Tracks whether scx_enable() called scx_bypass(true). Used to balance bypass
46+ * depth on enable failure. Will be removed when bypass depth is moved into the
47+ * sched instance.
48+ */
49+ static bool scx_bypassed_for_enable ;
50+
4451static atomic_long_t scx_nr_rejected = ATOMIC_LONG_INIT (0 );
4552static atomic_long_t scx_hotplug_seq = ATOMIC_LONG_INIT (0 );
4653
@@ -975,6 +982,30 @@ static void refill_task_slice_dfl(struct scx_sched *sch, struct task_struct *p)
975982 __scx_add_event (sch , SCX_EV_REFILL_SLICE_DFL , 1 );
976983}
977984
985+ static void local_dsq_post_enq (struct scx_dispatch_q * dsq , struct task_struct * p ,
986+ u64 enq_flags )
987+ {
988+ struct rq * rq = container_of (dsq , struct rq , scx .local_dsq );
989+ bool preempt = false;
990+
991+ /*
992+ * If @rq is in balance, the CPU is already vacant and looking for the
993+ * next task to run. No need to preempt or trigger resched after moving
994+ * @p into its local DSQ.
995+ */
996+ if (rq -> scx .flags & SCX_RQ_IN_BALANCE )
997+ return ;
998+
999+ if ((enq_flags & SCX_ENQ_PREEMPT ) && p != rq -> curr &&
1000+ rq -> curr -> sched_class == & ext_sched_class ) {
1001+ rq -> curr -> scx .slice = 0 ;
1002+ preempt = true;
1003+ }
1004+
1005+ if (preempt || sched_class_above (& ext_sched_class , rq -> curr -> sched_class ))
1006+ resched_curr (rq );
1007+ }
1008+
9781009static void dispatch_enqueue (struct scx_sched * sch , struct scx_dispatch_q * dsq ,
9791010 struct task_struct * p , u64 enq_flags )
9801011{
@@ -1086,22 +1117,10 @@ static void dispatch_enqueue(struct scx_sched *sch, struct scx_dispatch_q *dsq,
10861117 if (enq_flags & SCX_ENQ_CLEAR_OPSS )
10871118 atomic_long_set_release (& p -> scx .ops_state , SCX_OPSS_NONE );
10881119
1089- if (is_local ) {
1090- struct rq * rq = container_of (dsq , struct rq , scx .local_dsq );
1091- bool preempt = false;
1092-
1093- if ((enq_flags & SCX_ENQ_PREEMPT ) && p != rq -> curr &&
1094- rq -> curr -> sched_class == & ext_sched_class ) {
1095- rq -> curr -> scx .slice = 0 ;
1096- preempt = true;
1097- }
1098-
1099- if (preempt || sched_class_above (& ext_sched_class ,
1100- rq -> curr -> sched_class ))
1101- resched_curr (rq );
1102- } else {
1120+ if (is_local )
1121+ local_dsq_post_enq (dsq , p , enq_flags );
1122+ else
11031123 raw_spin_unlock (& dsq -> lock );
1104- }
11051124}
11061125
11071126static void task_unlink_from_dsq (struct task_struct * p ,
@@ -1625,6 +1644,8 @@ static void move_local_task_to_local_dsq(struct task_struct *p, u64 enq_flags,
16251644
16261645 dsq_mod_nr (dst_dsq , 1 );
16271646 p -> scx .dsq = dst_dsq ;
1647+
1648+ local_dsq_post_enq (dst_dsq , p , enq_flags );
16281649}
16291650
16301651/**
@@ -2402,7 +2423,7 @@ static void put_prev_task_scx(struct rq *rq, struct task_struct *p,
24022423 * ops.enqueue() that @p is the only one available for this cpu,
24032424 * which should trigger an explicit follow-up scheduling event.
24042425 */
2405- if (sched_class_above (& ext_sched_class , next -> sched_class )) {
2426+ if (next && sched_class_above (& ext_sched_class , next -> sched_class )) {
24062427 WARN_ON_ONCE (!(sch -> ops .flags & SCX_OPS_ENQ_LAST ));
24072428 do_enqueue_task (rq , p , SCX_ENQ_LAST , -1 );
24082429 } else {
@@ -2425,7 +2446,7 @@ static struct task_struct *
24252446do_pick_task_scx (struct rq * rq , struct rq_flags * rf , bool force_scx )
24262447{
24272448 struct task_struct * prev = rq -> curr ;
2428- bool keep_prev , kick_idle = false ;
2449+ bool keep_prev ;
24292450 struct task_struct * p ;
24302451
24312452 /* see kick_cpus_irq_workfn() */
@@ -2467,12 +2488,8 @@ do_pick_task_scx(struct rq *rq, struct rq_flags *rf, bool force_scx)
24672488 refill_task_slice_dfl (rcu_dereference_sched (scx_root ), p );
24682489 } else {
24692490 p = first_local_task (rq );
2470- if (!p ) {
2471- if (kick_idle )
2472- scx_kick_cpu (rcu_dereference_sched (scx_root ),
2473- cpu_of (rq ), SCX_KICK_IDLE );
2491+ if (!p )
24742492 return NULL ;
2475- }
24762493
24772494 if (unlikely (!p -> scx .slice )) {
24782495 struct scx_sched * sch = rcu_dereference_sched (scx_root );
@@ -3575,7 +3592,7 @@ static void scx_sched_free_rcu_work(struct work_struct *work)
35753592 int node ;
35763593
35773594 irq_work_sync (& sch -> error_irq_work );
3578- kthread_stop (sch -> helper -> task );
3595+ kthread_destroy_worker (sch -> helper );
35793596
35803597 free_percpu (sch -> pcpu );
35813598
@@ -4318,6 +4335,11 @@ static void scx_disable_workfn(struct kthread_work *work)
43184335 scx_dsp_max_batch = 0 ;
43194336 free_kick_syncs ();
43204337
4338+ if (scx_bypassed_for_enable ) {
4339+ scx_bypassed_for_enable = false;
4340+ scx_bypass (false);
4341+ }
4342+
43214343 mutex_unlock (& scx_enable_mutex );
43224344
43234345 WARN_ON_ONCE (scx_set_enable_state (SCX_DISABLED ) != SCX_DISABLING );
@@ -4786,7 +4808,7 @@ static struct scx_sched *scx_alloc_and_add_sched(struct sched_ext_ops *ops)
47864808 return sch ;
47874809
47884810err_stop_helper :
4789- kthread_stop (sch -> helper -> task );
4811+ kthread_destroy_worker (sch -> helper );
47904812err_free_pcpu :
47914813 free_percpu (sch -> pcpu );
47924814err_free_gdsqs :
@@ -4970,6 +4992,7 @@ static int scx_enable(struct sched_ext_ops *ops, struct bpf_link *link)
49704992 * Init in bypass mode to guarantee forward progress.
49714993 */
49724994 scx_bypass (true);
4995+ scx_bypassed_for_enable = true;
49734996
49744997 for (i = SCX_OPI_NORMAL_BEGIN ; i < SCX_OPI_NORMAL_END ; i ++ )
49754998 if (((void (* * )(void ))ops )[i ])
@@ -5067,6 +5090,7 @@ static int scx_enable(struct sched_ext_ops *ops, struct bpf_link *link)
50675090 scx_task_iter_stop (& sti );
50685091 percpu_up_write (& scx_fork_rwsem );
50695092
5093+ scx_bypassed_for_enable = false;
50705094 scx_bypass (false);
50715095
50725096 if (!scx_tryset_enable_state (SCX_ENABLED , SCX_ENABLING )) {
0 commit comments