mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* sched/deadline: total_bw leak when a task leaves SCHED_DEADLINE while not queued
@ 2026-10-29 21:55 Tejun Heo
  2026-10-30  9:22 ` Juri Lelli
  0 siblings, 1 reply; 2+ messages in thread
From: Tejun Heo @ 2026-10-29 21:55 UTC (permalink / raw)
  To: Juri Lelli, Peter Zijlstra
  Cc: Ingo Molnar, Vincent Guittot, Dietmar Eggemann,
	Valentin Schneider, K Prateek Nayak, Luca Abeni, Andrea Righi,
	sched-ext, linux-kernel

Hello,

A SCHED_DEADLINE task that is switched to another policy while it isn't
queued (sleeping, or stopped with SIGSTOP) leaves its bandwidth in the root
domain's total_bw. The bandwidth stays after the task exits. The leak
happens as follows.

1. sched_dl_overflow() doesn't subtract the bandwidth of a task leaving
   DEADLINE and leaves that to switched_from_dl().
2. switched_from_dl() calls task_non_contending() only for a queued task.
   task_non_contending() releases the bandwidth right away if the 0-lag time
   has passed and otherwise arms the inactive timer, and
   inactive_task_timer() releases it once the task is no longer dl_task().
3. For a task that isn't queued, the bandwidth is released only if its
   inactive timer is still pending from its dequeue. No timer is pending if
   the task never ran as DEADLINE, or if it already fired while the task
   slept. In the latter case the task was still DEADLINE when the timer
   fired, so it only dropped running_bw. Either way, nothing releases the
   bandwidth.

Repeating it fills total_bw up to the admission cap. After that,
sched_setattr(SCHED_DEADLINE) and CPU offline fail with -EBUSY, and so does
enabling a sched_ext scheduler, because attaching the ext dl_server
bandwidth fails:

  sched_ext: failed to attach ext_server on CPU 0 (-16)
  sched_ext: simple: scx_root_enable() failed (-16)

The reproducer below needs root and debugfs, and assumes x86-64 for the
syscall number 314.

  import ctypes, os, signal, time
  libc = ctypes.CDLL(None, use_errno=True)
  class SchedAttr(ctypes.Structure):
      _fields_ = [("size", ctypes.c_uint32), ("policy", ctypes.c_uint32),
                  ("flags", ctypes.c_uint64), ("nice", ctypes.c_int32),
                  ("prio", ctypes.c_uint32), ("runtime", ctypes.c_uint64),
                  ("deadline", ctypes.c_uint64), ("period", ctypes.c_uint64)]
  def setattr_(pid, policy, runtime=0, period=0):
      a = SchedAttr(ctypes.sizeof(SchedAttr), policy, 0, 0, 0, runtime, period, period)
      if libc.syscall(314, pid, ctypes.byref(a), 0):      # sched_setattr
          raise OSError(ctypes.get_errno(), "sched_setattr")
  def total_bw():
      s = open("/sys/kernel/debug/sched/debug").read().split("dl_rq[0]:")[1]
      return int(s.split("dl_bw->total_bw")[1].split(":")[1].split()[0])
  def trial(name, body, stop=False):
      pid = os.fork()
      if pid == 0:
          if body == "spin":
              while True:
                  pass
          while True:
              time.sleep(3600)
      time.sleep(0.05)
      bw0 = total_bw()
      setattr_(pid, 6, runtime=2_000_000, period=10_000_000)  # DEADLINE 2ms/10ms
      if stop:
          os.kill(pid, signal.SIGSTOP)
          time.sleep(0.02)
      setattr_(pid, 0)                                         # back to OTHER
      os.kill(pid, signal.SIGKILL)
      os.waitpid(pid, 0)
      time.sleep(0.05)
      print(f"{name:24s} leaked total_bw {total_bw() - bw0:7d} (0.2 CPU = 209715)")
  trial("sleeping dl>other", "sleep")
  trial("stopped dl>other", "spin", stop=True)
  trial("running dl>other", "spin")                            # control

On mainline 4dd16e31135e it prints:

  sleeping dl>other        leaked total_bw  209715 (0.2 CPU = 209715)
  stopped dl>other         leaked total_bw  209715 (0.2 CPU = 209715)
  running dl>other         leaked total_bw       0 (0.2 CPU = 209715)

Thanks.

--
tejun

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-10-30  9:22 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-29 21:55 sched/deadline: total_bw leak when a task leaves SCHED_DEADLINE while not queued Tejun Heo
2026-10-30  9:22 ` Juri Lelli

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®