The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=b602ba1b5fd92bb226e32f5720885f856a5cb0bb
commit b602ba1b5fd92bb226e32f5720885f856a5cb0bb Author: Konstantin Belousov <[email protected]> AuthorDate: 2026-01-22 13:38:20 +0000 Commit: Konstantin Belousov <[email protected]> CommitDate: 2026-01-29 18:11:56 +0000 net/iflib.c: move out scheduler-depended code into the hook Add sched_find_l2_neighbor(). This really should be not scheduler-depended, in does not have anything to do with scheduler at all. But for now keep the same code structure. Reviewed by: olce Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D54831 --- sys/kern/sched_4bsd.c | 7 +++++ sys/kern/sched_shim.c | 1 + sys/kern/sched_ule.c | 68 ++++++++++++++++++++++++++++++++++++++++++ sys/net/iflib.c | 82 ++------------------------------------------------- sys/sys/sched.h | 8 +++++ 5 files changed, 87 insertions(+), 79 deletions(-) diff --git a/sys/kern/sched_4bsd.c b/sys/kern/sched_4bsd.c index 03e7b71d3fe6..11baf9d2bdfa 100644 --- a/sys/kern/sched_4bsd.c +++ b/sys/kern/sched_4bsd.c @@ -1854,6 +1854,12 @@ sched_4bsd_do_timer_accounting(void) #endif } +static int +sched_4bsd_find_l2_neighbor(int cpu) +{ + return (-1); +} + struct sched_instance sched_4bsd_instance = { #define SLOT(name) .name = sched_4bsd_##name SLOT(load), @@ -1897,6 +1903,7 @@ struct sched_instance sched_4bsd_instance = { SLOT(tdname), SLOT(clear_tdname), SLOT(do_timer_accounting), + SLOT(find_l2_neighbor), SLOT(init), SLOT(init_ap), SLOT(setup), diff --git a/sys/kern/sched_shim.c b/sys/kern/sched_shim.c index d2f0b5749752..816d0b44bb52 100644 --- a/sys/kern/sched_shim.c +++ b/sys/kern/sched_shim.c @@ -94,6 +94,7 @@ DEFINE_SHIM0(sizeof_thread, int, sched_sizeof_thread) DEFINE_SHIM1(tdname, char *, sched_tdname, struct thread *, td) DEFINE_SHIM1(clear_tdname, void, sched_clear_tdname, struct thread *, td) DEFINE_SHIM0(do_timer_accounting, bool, sched_do_timer_accounting) +DEFINE_SHIM1(find_l2_neighbor, int, sched_find_l2_neighbor, int, cpu) DEFINE_SHIM0(init_ap, void, schedinit_ap) static char sched_name[32] = "ULE"; diff --git a/sys/kern/sched_ule.c b/sys/kern/sched_ule.c index 22257b2c0d7a..7a745619480d 100644 --- a/sys/kern/sched_ule.c +++ b/sys/kern/sched_ule.c @@ -3360,6 +3360,73 @@ sched_ule_do_timer_accounting(void) return (true); } +#ifdef SMP +static int +sched_ule_find_child_with_core(int cpu, struct cpu_group *grp) +{ + int i; + + if (grp->cg_children == 0) + return (-1); + + MPASS(grp->cg_child); + for (i = 0; i < grp->cg_children; i++) { + if (CPU_ISSET(cpu, &grp->cg_child[i].cg_mask)) + return (i); + } + + return (-1); +} + +static int +sched_ule_find_l2_neighbor(int cpu) +{ + struct cpu_group *grp; + int i; + + grp = cpu_top; + if (grp == NULL) + return (-1); + + /* + * Find the smallest CPU group that contains the given core. + */ + i = 0; + while ((i = sched_ule_find_child_with_core(cpu, grp)) != -1) { + /* + * If the smallest group containing the given CPU has less + * than two members, we conclude the given CPU has no + * L2 neighbor. + */ + if (grp->cg_child[i].cg_count <= 1) + return (-1); + grp = &grp->cg_child[i]; + } + + /* Must share L2. */ + if (grp->cg_level > CG_SHARE_L2 || grp->cg_level == CG_SHARE_NONE) + return (-1); + + /* + * Select the first member of the set that isn't the reference + * CPU, which at this point is guaranteed to exist. + */ + for (i = 0; i < CPU_SETSIZE; i++) { + if (CPU_ISSET(i, &grp->cg_mask) && i != cpu) + return (i); + } + + /* Should never be reached */ + return (-1); +} +#else +static int +sched_ule_find_l2_neighbor(int cpu) +{ + return (-1); +} +#endif + struct sched_instance sched_ule_instance = { #define SLOT(name) .name = sched_ule_##name SLOT(load), @@ -3403,6 +3470,7 @@ struct sched_instance sched_ule_instance = { SLOT(tdname), SLOT(clear_tdname), SLOT(do_timer_accounting), + SLOT(find_l2_neighbor), SLOT(init), SLOT(init_ap), SLOT(setup), diff --git a/sys/net/iflib.c b/sys/net/iflib.c index b0e4bb9470c9..8e2fd257ca74 100644 --- a/sys/net/iflib.c +++ b/sys/net/iflib.c @@ -29,7 +29,6 @@ #include "opt_inet.h" #include "opt_inet6.h" #include "opt_acpi.h" -#include "opt_sched.h" #include <sys/param.h> #include <sys/types.h> @@ -40,8 +39,10 @@ #include <sys/mutex.h> #include <sys/module.h> #include <sys/kobj.h> +#include <sys/proc.h> #include <sys/rman.h> #include <sys/sbuf.h> +#include <sys/sched.h> #include <sys/smp.h> #include <sys/socket.h> #include <sys/sockio.h> @@ -4813,83 +4814,6 @@ cpuid_advance(if_ctx_t ctx, unsigned int cpuid, unsigned int n) return (cpuid); } -#if defined(SMP) && defined(SCHED_ULE) -extern struct cpu_group *cpu_top; /* CPU topology */ - -static int -find_child_with_core(int cpu, struct cpu_group *grp) -{ - int i; - - if (grp->cg_children == 0) - return (-1); - - MPASS(grp->cg_child); - for (i = 0; i < grp->cg_children; i++) { - if (CPU_ISSET(cpu, &grp->cg_child[i].cg_mask)) - return (i); - } - - return (-1); -} - - -/* - * Find an L2 neighbor of the given CPU or return -1 if none found. This - * does not distinguish among multiple L2 neighbors if the given CPU has - * more than one (it will always return the same result in that case). - */ -static int -find_l2_neighbor(int cpu) -{ - struct cpu_group *grp; - int i; - - grp = cpu_top; - if (grp == NULL) - return (-1); - - /* - * Find the smallest CPU group that contains the given core. - */ - i = 0; - while ((i = find_child_with_core(cpu, grp)) != -1) { - /* - * If the smallest group containing the given CPU has less - * than two members, we conclude the given CPU has no - * L2 neighbor. - */ - if (grp->cg_child[i].cg_count <= 1) - return (-1); - grp = &grp->cg_child[i]; - } - - /* Must share L2. */ - if (grp->cg_level > CG_SHARE_L2 || grp->cg_level == CG_SHARE_NONE) - return (-1); - - /* - * Select the first member of the set that isn't the reference - * CPU, which at this point is guaranteed to exist. - */ - for (i = 0; i < CPU_SETSIZE; i++) { - if (CPU_ISSET(i, &grp->cg_mask) && i != cpu) - return (i); - } - - /* Should never be reached */ - return (-1); -} - -#else -static int -find_l2_neighbor(int cpu) -{ - - return (-1); -} -#endif - /* * CPU mapping behaviors * --------------------- @@ -4942,7 +4866,7 @@ get_cpuid_for_queue(if_ctx_t ctx, unsigned int base_cpuid, unsigned int qid, unsigned int rx_cpuid; rx_cpuid = cpuid_advance(ctx, base_cpuid, qid); - l2_neighbor = find_l2_neighbor(rx_cpuid); + l2_neighbor = sched_find_l2_neighbor(rx_cpuid); if (l2_neighbor != -1) { return (l2_neighbor); } diff --git a/sys/sys/sched.h b/sys/sys/sched.h index 9c78452432b4..3ba40fb191d3 100644 --- a/sys/sys/sched.h +++ b/sys/sys/sched.h @@ -243,6 +243,13 @@ void schedinit_ap(void); bool sched_do_timer_accounting(void); +/* + * Find an L2 neighbor of the given CPU or return -1 if none found. This + * does not distinguish among multiple L2 neighbors if the given CPU has + * more than one (it will always return the same result in that case). + */ +int sched_find_l2_neighbor(int cpu); + struct sched_instance { int (*load)(void); int (*rr_interval)(void); @@ -285,6 +292,7 @@ struct sched_instance { char *(*tdname)(struct thread *td); void (*clear_tdname)(struct thread *td); bool (*do_timer_accounting)(void); + int (*find_l2_neighbor)(int cpuid); void (*init)(void); void (*init_ap)(void); void (*setup)(void);
