Skip to content

Commit 10a3975

Browse files
authored
Merge pull request #12 from jserv/sched
Trim kernel/sched via debug.c and deadline.c gates
2 parents 3bf761f + 9f1c556 commit 10a3975

3 files changed

Lines changed: 310 additions & 6 deletions

File tree

‎build.sh‎

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,14 @@ LINUX_VERSION=7.0
2323

2424
BINUTILS_URL=https://ftp.gnu.org/gnu/binutils/binutils-${BINUTILS_VERSION}.tar.xz
2525
GCC_URL=https://ftp.gnu.org/gnu/gcc/gcc-${GCC_VERSION}/gcc-${GCC_VERSION}.tar.xz
26-
UCLIBC_NG_URL=https://downloads.uclibc-ng.org/releases/${UCLIBC_NG_VERSION}/uClibc-ng-${UCLIBC_NG_VERSION}.tar.xz
26+
# GitHub auto-archive. The canonical mirror at downloads.uclibc-ng.org
27+
# has been observed returning HTTP 522 (Cloudflare-to-origin failure)
28+
# for extended windows; GitHub's tag-based source archive is permanent
29+
# and byte-equivalent to the upstream tarball content (same 5,527-file
30+
# tree, only the top-level directory uses lowercase 'u' which we rename
31+
# back below to keep configs/uClibc-ng-*.config and the rest of this
32+
# script unchanged).
33+
UCLIBC_NG_URL=https://github.com/wbx-github/uclibc-ng/archive/refs/tags/v${UCLIBC_NG_VERSION}.tar.gz
2734
BUSYBOX_URL=https://busybox.net/downloads/busybox-${BUSYBOX_VERSION}.tar.bz2
2835
LINUX_URL=https://www.kernel.org/pub/linux/kernel/v7.x/linux-${LINUX_VERSION}.tar.xz
2936

@@ -63,7 +70,7 @@ mkdir -p "${LOGDIR}" "${STATE_DIR}"
6370
# To populate missing checksums: sha256sum downloads/*
6471
CHECKSUM_binutils="binutils-${BINUTILS_VERSION}.tar.xz=d75a94f4d73e7a4086f7513e67e439e8fcdcbb726ffe63f4661744e6256b2cf2"
6572
CHECKSUM_gcc="gcc-${GCC_VERSION}.tar.xz=438fd996826b0c82485a29da03a72d71d6e3541a83ec702df4271f6fe025d24e"
66-
CHECKSUM_uclibc="uClibc-ng-${UCLIBC_NG_VERSION}.tar.xz=8bc734b584e23ff6ae3d0ebb4c0fb1d1d814c58c82822b93130d436afa7ace8b"
73+
CHECKSUM_uclibc="v${UCLIBC_NG_VERSION}.tar.gz=f49704e0affc75fde9ee4e870c20e53c1d807eca2a4683377b359b8361e84312"
6774
CHECKSUM_busybox="busybox-${BUSYBOX_VERSION}.tar.bz2=3311dff32e746499f4df0d5df04d7eb396382d7e108bb9250e7b519b837043a4"
6875
CHECKSUM_linux="linux-${LINUX_VERSION}.tar.xz=bb7f6d80b387c757b7d14bb93028fcb90f793c5c0d367736ee815a100b3891f0"
6976

@@ -410,7 +417,12 @@ build_uClibc() {
410417
echo "BUILD: building uClibc-${UCLIBC_NG_VERSION}"
411418
fetch_file "${UCLIBC_NG_URL}" "${CHECKSUM_uclibc}"
412419

413-
extract_source "uClibc-ng-${UCLIBC_NG_VERSION}.tar.xz" "uClibc-ng-${UCLIBC_NG_VERSION}" -xJf
420+
extract_source "v${UCLIBC_NG_VERSION}.tar.gz" "uClibc-ng-${UCLIBC_NG_VERSION}" -xzf
421+
# GitHub source archive unpacks to lowercase 'uclibc-ng-X.Y.Z'; rename
422+
# to the canonical-tarball capitalization so configs/ and stage_clean
423+
# references stay valid. extract_source's own "reuse" check above
424+
# already short-circuits on subsequent runs once the rename has taken.
425+
[ -d "uClibc-ng-${UCLIBC_NG_VERSION}" ] || mv "uclibc-ng-${UCLIBC_NG_VERSION}" "uClibc-ng-${UCLIBC_NG_VERSION}"
414426
cp configs/uClibc-ng-${UCLIBC_NG_VERSION}-${FLAVOR}.config uClibc-ng-${UCLIBC_NG_VERSION}/.config
415427
cd uClibc-ng-${UCLIBC_NG_VERSION}
416428

@@ -654,7 +666,7 @@ build_linux() {
654666
cd linux-${LINUX_VERSION}
655667

656668
# Apply linux-tiny patches for reduced memory footprint and LTO support
657-
for p in ../patches/0002-*.patch ../patches/0003-*.patch ../patches/0004-*.patch ../patches/0005-*.patch ../patches/0006-*.patch ../patches/0010-*.patch ../patches/0011-*.patch; do
669+
for p in ../patches/0002-*.patch ../patches/0003-*.patch ../patches/0004-*.patch ../patches/0005-*.patch ../patches/0006-*.patch ../patches/0010-*.patch ../patches/0011-*.patch ../patches/0012-*.patch ../patches/0013-*.patch; do
658670
[ -f "${p}" ] || continue
659671
apply_patch_once "${p}"
660672
done
@@ -896,6 +908,29 @@ build_linux() {
896908
echo "# CONFIG_STACKPROTECTOR is not set" >>.config
897909
echo "# CONFIG_STACKPROTECTOR_STRONG is not set" >>.config
898910

911+
# Scheduler trim: Linux 7.0 removed CONFIG_SCHED_DEBUG and unified
912+
# debug.c into build_utility.c. Patch 0012 reintroduces a knob
913+
# (SCHED_DEBUG_OUTPUT, default y) that wraps debug.c body in #ifdef
914+
# and provides empty stubs for the externally-called symbols.
915+
# /proc/<pid>/sched returns empty seq_file; OOPS sched_show_task
916+
# path is unaffected (defined in core.c). Measured: -4,278 bytes /
917+
# 16 symbols on the production vmlinux .text.
918+
echo "# CONFIG_SCHED_DEBUG_OUTPUT is not set" >>.config
919+
920+
# Patch 0013 mirrors 0012 for deadline.c: SCHED_DEADLINE_CLASS
921+
# default y; set n to wrap deadline.c body in #ifdef and substitute
922+
# a stub class (DEFINE_SCHED_CLASS(dl) with pick_task=NULL_returner,
923+
# all other callbacks NULL). __checkparam_dl returns false so
924+
# sched_setattr with policy=6 is rejected with -EPERM and no task
925+
# ever joins SCHED_DEADLINE. Any later attempt to program a DL
926+
# server is rejected with -EOPNOTSUPP, so the scheduler must also
927+
# keep the cgroup-bandwidth/group-sched knobs below disabled.
928+
# Measured: -10,530 bytes / 81 symbols.
929+
echo "# CONFIG_SCHED_DEADLINE_CLASS is not set" >>.config
930+
echo "# CONFIG_PSI is not set" >>.config
931+
echo "# CONFIG_CGROUPS is not set" >>.config
932+
echo "# CONFIG_SCHED_AUTOGROUP is not set" >>.config
933+
899934
run_logged "olddefconfig" kernel_make olddefconfig
900935

901936
# Verify critical config options survived olddefconfig resolution.
@@ -953,7 +988,12 @@ build_linux() {
953988
"# CONFIG_DEBUG_BUGVERBOSE is not set" \
954989
"# CONFIG_RD_ZSTD is not set" \
955990
"# CONFIG_RD_LZ4 is not set" \
956-
"# CONFIG_RD_XZ is not set"; do
991+
"# CONFIG_RD_XZ is not set" \
992+
"# CONFIG_SCHED_DEBUG_OUTPUT is not set" \
993+
"# CONFIG_SCHED_DEADLINE_CLASS is not set" \
994+
"# CONFIG_PSI is not set" \
995+
"# CONFIG_CGROUPS is not set" \
996+
"# CONFIG_SCHED_AUTOGROUP is not set"; do
957997
if ! grep -q "^${opt}\$" .config; then
958998
echo "ERROR: expected '${opt}' in .config after olddefconfig"
959999
exit 1
@@ -1003,9 +1043,13 @@ build_linux() {
10031043
# STACKPROTECTOR_STRONG -- depends on STACKPROTECTOR=y
10041044
# LOGO/A11Y_BRAILLE_CONSOLE -- depend on the VT stack
10051045
# DEVTMPFS_MOUNT -- depends on DEVTMPFS=y
1046+
# CGROUP_SCHED/*_GROUP_SCHED/CFS_BANDWIDTH -- depend on CGROUPS=y
10061047
for sym in SHMEM AUDIT POSIX_MQUEUE SECURITY TASKSTATS PCI \
10071048
STACKPROTECTOR_STRONG LOGO A11Y_BRAILLE_CONSOLE \
1008-
DEVTMPFS_MOUNT; do
1049+
DEVTMPFS_MOUNT \
1050+
CGROUP_SCHED FAIR_GROUP_SCHED CFS_BANDWIDTH RT_GROUP_SCHED \
1051+
SCHED_CORE NUMA_BALANCING UCLAMP_TASK \
1052+
SCHED_THERMAL_PRESSURE SCHEDSTATS; do
10091053
if grep -q "^CONFIG_${sym}=y\$" .config; then
10101054
echo "ERROR: CONFIG_${sym}=y survived olddefconfig (subsystem disable broken?)"
10111055
exit 1
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
From: Jim Huang <jserv@ccns.ncku.edu.tw>
2+
Subject: [PATCH] tiny: sched: gate debug.c behind CONFIG_SCHED_DEBUG_OUTPUT
3+
4+
Linux 7.0 removed the historical CONFIG_SCHED_DEBUG gate; debug.c is now
5+
unconditionally included via build_utility.c. On a NOMMU image with no
6+
userspace reader of /proc/<pid>/sched, no debugfs sched-domain consumer,
7+
and no sysrq input device, the file is ~4KB of dead .text and .rodata.
8+
9+
Re-introduce a knob without resurrecting the old name (which other code
10+
still references in deprecation comments). CONFIG_SCHED_DEBUG_OUTPUT
11+
defaults to y so mainline behavior is preserved; setting it to n wraps
12+
the body of debug.c in #ifdef and provides empty stubs for the
13+
externally-called symbols that lack existing header stubs:
14+
15+
sched_debug_verbose -- topology.c reads this flag
16+
sysrq_sched_debug_show -- core.c show_state_filter
17+
resched_latency_warn -- core.c sched_tick latency check
18+
print_cfs_rq / print_rt_rq -- print_*_stats bodies in fair.c, rt.c
19+
print_dl_rq -- print_dl_stats body in deadline.c
20+
print_numa_stats -- print_cfs_stats body in fair.c
21+
(only when CONFIG_NUMA_BALANCING)
22+
proc_sched_show_task -- fs/proc/base.c /proc/<pid>/sched read
23+
proc_sched_set_task -- fs/proc/base.c /proc/<pid>/sched write
24+
update_sched_domain_debugfs -- topology.c sched-domain rebuild path
25+
dirty_sched_domain_sysctl -- topology.c sched-domain sysctl path
26+
27+
OOPS/panic backtraces are unaffected because sched_show_task and
28+
dump_cpu_task live in core.c, not debug.c. /proc/<pid>/sched returns an
29+
empty seq_file when read. Boot-path callers silently no-op.
30+
31+
Measured on Cortex-M4 nommu mps2-an386 (linux-7.0): SCHED_DEBUG_OUTPUT=n
32+
drops 4,278 bytes / 16 symbols from .text per nm --size-sort against the
33+
production vmlinux.
34+
35+
---
36+
init/Kconfig | 14 ++++++++++++++
37+
kernel/sched/debug.c | 22 ++++++++++++++++++++++
38+
2 files changed, 36 insertions(+)
39+
40+
diff --git a/init/Kconfig b/init/Kconfig
41+
--- a/init/Kconfig
42+
+++ b/init/Kconfig
43+
@@ -932,6 +932,20 @@ config SCHED_PROXY_EXEC
44+
This option enables proxy execution, a mechanism for mutex-owning
45+
tasks to inherit the scheduling context of higher priority waiters.
46+
47+
+config SCHED_DEBUG_OUTPUT
48+
+ bool "Scheduler debug/output paths"
49+
+ default y
50+
+ help
51+
+ Build kernel/sched/debug.c, which provides /proc/<pid>/sched,
52+
+ /sys/kernel/debug/sched/* (when DEBUG_FS=y), the sysrq scheduler
53+
+ dump, and the print_cfs_rq / print_rt_rq / print_dl_rq /
54+
+ print_numa_stats formatters.
55+
+
56+
+ Say N on size-constrained NOMMU images that never read
57+
+ /proc/<pid>/sched and have no debugfs sched-domain consumer.
58+
+ Boot-path callers become no-ops; OOPS/panic backtraces are
59+
+ unaffected (sched_show_task lives in core.c).
60+
+
61+
endmenu
62+
63+
#
64+
diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c
65+
--- a/kernel/sched/debug.c
66+
+++ b/kernel/sched/debug.c
67+
@@ -9,6 +9,8 @@
68+
#include <linux/debugfs.h>
69+
#include <linux/nmi.h>
70+
#include "sched.h"
71+
+
72+
+#ifdef CONFIG_SCHED_DEBUG_OUTPUT
73+
74+
/*
75+
* This allows printing both to /sys/kernel/debug/sched/debug and
76+
@@ -1388,3 +1390,25 @@ void resched_latency_warn(int cpu, u64 latency)
77+
cpu, latency, cpu_rq(cpu)->ticks_without_resched);
78+
dump_stack();
79+
}
80+
+
81+
+#else /* !CONFIG_SCHED_DEBUG_OUTPUT */
82+
+
83+
+__read_mostly bool sched_debug_verbose;
84+
+
85+
+void sysrq_sched_debug_show(void) { }
86+
+void resched_latency_warn(int cpu, u64 latency) { }
87+
+void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) { }
88+
+void print_rt_rq(struct seq_file *m, int cpu, struct rt_rq *rt_rq) { }
89+
+void print_dl_rq(struct seq_file *m, int cpu, struct dl_rq *dl_rq) { }
90+
+#ifdef CONFIG_NUMA_BALANCING
91+
+void print_numa_stats(struct seq_file *m, int node, unsigned long tsf,
92+
+ unsigned long tpf, unsigned long gsf, unsigned long gpf)
93+
+{ }
94+
+#endif
95+
+void proc_sched_show_task(struct task_struct *p, struct pid_namespace *ns,
96+
+ struct seq_file *m) { }
97+
+void proc_sched_set_task(struct task_struct *p) { }
98+
+void update_sched_domain_debugfs(void) { }
99+
+void dirty_sched_domain_sysctl(int cpu) { }
100+
+
101+
+#endif /* CONFIG_SCHED_DEBUG_OUTPUT */
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
From: Jim Huang <jserv@ccns.ncku.edu.tw>
2+
Subject: [PATCH] tiny: sched: gate deadline.c behind CONFIG_SCHED_DEADLINE_CLASS
3+
4+
Linux 7.0 deleted the historical CONFIG_SCHED_DEADLINE gate; deadline.c
5+
is now unconditionally included via build_policy.c. On a NOMMU image
6+
that never sets SCHED_DEADLINE policy (BusyBox CHRT applet is off, no
7+
init script issues sched_setattr with policy=6), the file is ~10.5KB of
8+
dead .text plus its DL bandwidth/server bookkeeping.
9+
10+
Re-introduce a knob without resurrecting the old name.
11+
CONFIG_SCHED_DEADLINE_CLASS defaults to y so mainline behavior is
12+
preserved; setting it to n wraps the body of deadline.c in #ifdef and
13+
provides a minimal stub class plus stubs for every externally-called
14+
helper. The stub class is registered via DEFINE_SCHED_CLASS(dl) so it
15+
lands in the __dl_sched_class linker section between stop and rt --
16+
core.c::sched_class_above() BUG_ON checks at sched_init pass. Only
17+
.pick_task is implemented (returns NULL); all other callbacks remain
18+
NULL because they fire only for tasks already in the class, and
19+
__checkparam_dl() rejects every attribute set so no task can ever join.
20+
21+
External-API stubs match include/linux/sched/deadline.h and
22+
kernel/sched/sched.h declarations:
23+
24+
Class chain:
25+
dl_sched_class -- empty class with pick_task=NULL
26+
Init paths (called from core.c, fair.c, topology.c):
27+
init_dl_bw / init_dl_rq / init_dl_entity
28+
init_sched_dl_class / sched_init_dl_servers
29+
Sysctl/global validation (called from rt.c sysctl handler):
30+
sched_dl_global_validate / sched_dl_do_global
31+
Syscall path (sched_setattr / sched_getattr):
32+
sched_dl_overflow -- returns -EPERM, blocks DL admission
33+
__checkparam_dl -- returns false, blocks DL attribute sets
34+
__setparam_dl / __getparam_dl / dl_param_changed
35+
CPU hotplug / cpuset:
36+
dl_cpuset_cpumask_can_shrink -- cpuset shrink validation
37+
DL server (used by fair.c to back SCHED_OTHER bandwidth):
38+
dl_server_init / _start / _stop / _update / _update_idle
39+
__dl_server_attach_root / dl_server_apply_params
40+
Bandwidth scaling helper:
41+
dl_scaled_delta_exec -- returns delta_exec unchanged
42+
Globals visible to topology.c / cgroup code:
43+
dl_cookie / dl_bw_visited
44+
Bandwidth-management helpers used by core.c / cpuset:
45+
dl_bw_deactivate / dl_bw_alloc / dl_bw_free
46+
47+
The DL-server feature backs CFS bandwidth via a deadline entity per
48+
runqueue. When the class is disabled, any attempt to program a DL
49+
server fails with -EOPNOTSUPP instead of pretending to succeed; the
50+
build disables the scheduler cgroup bandwidth knobs accordingly.
51+
52+
Measured on Cortex-M4 nommu mps2-an386 (linux-7.0): SCHED_DEADLINE_CLASS=n
53+
drops 10,530 bytes / 81 symbols from .text per nm --size-sort.
54+
55+
---
56+
init/Kconfig | 13 +++++++++
57+
kernel/sched/deadline.c | 60 ++++++++++++++++++++++++++++++++++++
58+
2 files changed, 73 insertions(+)
59+
60+
diff --git a/init/Kconfig b/init/Kconfig
61+
--- a/init/Kconfig
62+
+++ b/init/Kconfig
63+
@@ -933,6 +933,19 @@ config SCHED_PROXY_EXEC
64+
This option enables proxy execution, a mechanism for mutex-owning
65+
tasks to inherit the scheduling context of higher priority waiters.
66+
67+
+config SCHED_DEADLINE_CLASS
68+
+ bool "SCHED_DEADLINE earliest-deadline-first scheduling class"
69+
+ default y
70+
+ help
71+
+ Build kernel/sched/deadline.c, which implements the SCHED_DEADLINE
72+
+ policy (EDF + Constant Bandwidth Server) and the deadline-server
73+
+ bandwidth backing for SCHED_OTHER.
74+
+
75+
+ Say N on size-constrained NOMMU images that never set SCHED_DEADLINE
76+
+ policy and need every byte back. __checkparam_dl rejects all DL
77+
+ attribute sets; sched_setattr with policy=6 returns -EPERM. Any
78+
+ later attempt to program a DL server fails with -EOPNOTSUPP.
79+
+
80+
endmenu
81+
82+
#
83+
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
84+
--- a/kernel/sched/deadline.c
85+
+++ b/kernel/sched/deadline.c
86+
@@ -20,6 +20,8 @@
87+
#include <uapi/linux/sched/types.h>
88+
#include "sched.h"
89+
#include "pelt.h"
90+
+
91+
+#ifdef CONFIG_SCHED_DEADLINE_CLASS
92+
93+
/*
94+
* Default limits for DL period; on the top end we guard against small util
95+
@@ -3841,3 +3843,64 @@ void print_dl_stats(struct seq_file *m, int cpu)
96+
{
97+
print_dl_rq(m, cpu, &cpu_rq(cpu)->dl);
98+
}
99+
+
100+
+#else /* !CONFIG_SCHED_DEADLINE_CLASS */
101+
+
102+
+#include <linux/sched/deadline.h>
103+
+
104+
+/*
105+
+ * Stub deadline scheduling class. No task ever joins SCHED_DEADLINE
106+
+ * because __checkparam_dl rejects every attribute set, so all callbacks
107+
+ * except pick_task are unreachable and remain NULL. pick_task is the
108+
+ * one method the chain walk in pick_next_task_balance / pick_next_task
109+
+ * invokes unconditionally per class; returning NULL forwards control to
110+
+ * the next class (rt -> fair -> idle).
111+
+ */
112+
+
113+
+static struct task_struct *pick_task_dl_stub(struct rq *rq, struct rq_flags *rf)
114+
+{
115+
+ return NULL;
116+
+}
117+
+
118+
+DEFINE_SCHED_CLASS(dl) = {
119+
+ .pick_task = pick_task_dl_stub,
120+
+};
121+
+
122+
+u64 dl_cookie;
123+
+
124+
+bool dl_bw_visited(int cpu, u64 cookie) { return false; }
125+
+int dl_bw_deactivate(int cpu) { return 0; }
126+
+int dl_bw_alloc(int cpu, u64 dl_bw) { return 0; }
127+
+void dl_bw_free(int cpu, u64 dl_bw) { }
128+
+
129+
+void init_dl_bw(struct dl_bw *dl_b) { }
130+
+void init_dl_rq(struct dl_rq *dl_rq) { }
131+
+void init_dl_entity(struct sched_dl_entity *dl_se) { }
132+
+void __init init_sched_dl_class(void) { }
133+
+void sched_init_dl_servers(void) { }
134+
+
135+
+int sched_dl_global_validate(void) { return 0; }
136+
+void sched_dl_do_global(void) { }
137+
+int sched_dl_overflow(struct task_struct *p, int policy,
138+
+ const struct sched_attr *attr) { return -EPERM; }
139+
+void __setparam_dl(struct task_struct *p, const struct sched_attr *attr) { }
140+
+void __getparam_dl(struct task_struct *p, struct sched_attr *attr) { }
141+
+bool __checkparam_dl(const struct sched_attr *attr) { return false; }
142+
+bool dl_param_changed(struct task_struct *p, const struct sched_attr *attr)
143+
+{ return false; }
144+
+int dl_cpuset_cpumask_can_shrink(const struct cpumask *cur,
145+
+ const struct cpumask *trial) { return 1; }
146+
+s64 dl_scaled_delta_exec(struct rq *rq, struct sched_dl_entity *dl_se,
147+
+ s64 delta_exec) { return delta_exec; }
148+
+
149+
+void dl_server_init(struct sched_dl_entity *dl_se, struct rq *rq,
150+
+ dl_server_pick_f pick_task) { }
151+
+void dl_server_start(struct sched_dl_entity *dl_se) { }
152+
+void dl_server_stop(struct sched_dl_entity *dl_se) { }
153+
+void dl_server_update(struct sched_dl_entity *dl_se, s64 delta_exec) { }
154+
+void dl_server_update_idle(struct sched_dl_entity *dl_se, s64 delta_exec) { }
155+
+void __dl_server_attach_root(struct sched_dl_entity *dl_se, struct rq *rq) { }
156+
+int dl_server_apply_params(struct sched_dl_entity *dl_se, u64 runtime,
157+
+ u64 period, bool init) { return -EOPNOTSUPP; }
158+
+
159+
+#endif /* CONFIG_SCHED_DEADLINE_CLASS */

0 commit comments

Comments
 (0)