]> Git Repo - linux.git/commitdiff
Merge tag 'rcu.2023.02.10a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck...
authorLinus Torvalds <[email protected]>
Tue, 21 Feb 2023 18:45:51 +0000 (10:45 -0800)
committerLinus Torvalds <[email protected]>
Tue, 21 Feb 2023 18:45:51 +0000 (10:45 -0800)
Pull RCU updates from Paul McKenney:

 - Documentation updates

 - Miscellaneous fixes, perhaps most notably:

      - Throttling callback invocation based on the number of callbacks
        that are now ready to invoke instead of on the total number of
        callbacks

      - Several patches that suppress false-positive boot-time
        diagnostics, for example, due to lockdep not yet being
        initialized

      - Make expedited RCU CPU stall warnings dump stacks of any tasks
        that are blocking the stalled grace period. (Normal RCU CPU
        stall warnings have done this for many years)

      - Lazy-callback fixes to avoid delays during boot, suspend, and
        resume. (Note that lazy callbacks must be explicitly enabled, so
        this should not (yet) affect production use cases)

 - Make kfree_rcu() and friends take advantage of polled grace periods,
   thus reducing memory footprint by almost two orders of magnitude,
   admittedly on a microbenchmark

   This also begins the transition from kfree_rcu(p) to
   kfree_rcu_mightsleep(p). This transition was motivated by bugs where
   kfree_rcu(p), which can block, was typed instead of the intended
   kfree_rcu(p, rh)

 - SRCU updates, perhaps most notably fixing a bug that causes SRCU to
   fail when booted on a system with a non-zero boot CPU. This
   surprising situation actually happens for kdump kernels on the
   powerpc architecture

   This also adds an srcu_down_read() and srcu_up_read(), which act like
   srcu_read_lock() and srcu_read_unlock(), but allow an SRCU read-side
   critical section to be handed off from one task to another

 - Clean up the now-useless SRCU Kconfig option

   There are a few more commits that are not yet acked or pulled into
   maintainer trees, and these will be in a pull request for a later
   merge window

 - RCU-tasks updates, perhaps most notably these fixes:

      - A strange interaction between PID-namespace unshare and the
        RCU-tasks grace period that results in a low-probability but
        very real hang

      - A race between an RCU tasks rude grace period on a single-CPU
        system and CPU-hotplug addition of the second CPU that can
        result in a too-short grace period

      - A race between shrinking RCU tasks down to a single callback
        list and queuing a new callback to some other CPU, but where
        that queuing is delayed for more than an RCU grace period. This
        can result in that callback being stranded on the non-boot CPU

 - Torture-test updates and fixes

 - Torture-test scripting updates and fixes

 - Provide additional RCU CPU stall-warning information in kernels built
   with CONFIG_RCU_CPU_STALL_CPUTIME=y, and restore the full five-minute
   timeout limit for expedited RCU CPU stall warnings

* tag 'rcu.2023.02.10a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu: (80 commits)
  rcu/kvfree: Add kvfree_rcu_mightsleep() and kfree_rcu_mightsleep()
  kernel/notifier: Remove CONFIG_SRCU
  init: Remove "select SRCU"
  fs/quota: Remove "select SRCU"
  fs/notify: Remove "select SRCU"
  fs/btrfs: Remove "select SRCU"
  fs: Remove CONFIG_SRCU
  drivers/pci/controller: Remove "select SRCU"
  drivers/net: Remove "select SRCU"
  drivers/md: Remove "select SRCU"
  drivers/hwtracing/stm: Remove "select SRCU"
  drivers/dax: Remove "select SRCU"
  drivers/base: Remove CONFIG_SRCU
  rcu: Disable laziness if lazy-tracking says so
  rcu: Track laziness during boot and suspend
  rcu: Remove redundant call to rcu_boost_kthread_setaffinity()
  rcu: Allow up to five minutes expedited RCU CPU stall-warning timeouts
  rcu: Align the output of RCU CPU stall warning messages
  rcu: Add RCU stall diagnosis information
  sched: Add helper nr_context_switches_cpu()
  ...

1  2 
Documentation/admin-guide/kernel-parameters.txt
fs/locks.c
init/Kconfig
kernel/sched/core.c

index b642b8143fce106b6cce667c1acb44813e1bb439,5ac69d8549f91590f501d61442afc00048a363a6..2b0692a642a72e299f1c6a2edfcb240a54c83681
                        rcupdate.rcu_cpu_stall_timeout to be used (after
                        conversion from seconds to milliseconds).
  
+       rcupdate.rcu_cpu_stall_cputime= [KNL]
+                       Provide statistics on the cputime and count of
+                       interrupts and tasks during the sampling period. For
+                       multiple continuous RCU stalls, all sampling periods
+                       begin at half of the first RCU stall timeout.
+       rcupdate.rcu_exp_stall_task_details= [KNL]
+                       Print stack dumps of any tasks blocking the
+                       current expedited RCU grace period during an
+                       expedited RCU CPU stall warning.
        rcupdate.rcu_expedited= [KNL]
                        Use expedited grace-period primitives, for
                        example, synchronize_rcu_expedited() instead
        rdt=            [HW,X86,RDT]
                        Turn on/off individual RDT features. List is:
                        cmt, mbmtotal, mbmlocal, l3cat, l3cdp, l2cat, l2cdp,
 -                      mba.
 +                      mba, smba, bmec.
                        E.g. to turn on cmt and turn off mba use:
                                rdt=cmt,!mba
  
                        in situations with strict latency requirements (where
                        interruptions from clocksource watchdog are not
                        acceptable).
 +                      [x86] recalibrate: force recalibration against a HW timer
 +                      (HPET or PM timer) on systems whose TSC frequency was
 +                      obtained from HW or FW using either an MSR or CPUID(0x15).
 +                      Warn if the difference is more than 500 ppm.
 +                      [x86] watchdog: Use TSC as the watchdog clocksource with
 +                      which to check other HW timers (HPET or PM timer), but
 +                      only on systems where TSC has been deemed trustworthy.
 +                      This will be suppressed by an earlier tsc=nowatchdog and
 +                      can be overridden by a later tsc=nowatchdog.  A console
 +                      message will flag any such suppression or overriding.
  
        tsc_early_khz=  [X86] Skip early TSC calibration and use the given
                        value instead. Useful when the early TSC frequency discovery
diff --combined fs/locks.c
index 624c6ac92edef397875890aac7de1e23f06fc7cb,1909a9de242c8e6bd2c066c1641d669113f9b1c9..66b4eef09db57785b86c214e416660784081d1f7
@@@ -52,7 -52,6 +52,7 @@@
  #include <linux/capability.h>
  #include <linux/file.h>
  #include <linux/fdtable.h>
 +#include <linux/filelock.h>
  #include <linux/fs.h>
  #include <linux/init.h>
  #include <linux/security.h>
@@@ -234,7 -233,7 +234,7 @@@ locks_check_ctx_file_list(struct file *
                                char *list_type)
  {
        struct file_lock *fl;
 -      struct inode *inode = locks_inode(filp);
 +      struct inode *inode = file_inode(filp);
  
        list_for_each_entry(fl, list, fl_list)
                if (fl->fl_file == filp)
@@@ -888,7 -887,7 +888,7 @@@ posix_test_lock(struct file *filp, stru
  {
        struct file_lock *cfl;
        struct file_lock_context *ctx;
 -      struct inode *inode = locks_inode(filp);
 +      struct inode *inode = file_inode(filp);
        void *owner;
        void (*func)(void);
  
@@@ -1331,7 -1330,7 +1331,7 @@@ retry
  int posix_lock_file(struct file *filp, struct file_lock *fl,
                        struct file_lock *conflock)
  {
 -      return posix_lock_inode(locks_inode(filp), fl, conflock);
 +      return posix_lock_inode(file_inode(filp), fl, conflock);
  }
  EXPORT_SYMBOL(posix_lock_file);
  
@@@ -1630,7 -1629,7 +1630,7 @@@ EXPORT_SYMBOL(lease_get_mtime)
  int fcntl_getlease(struct file *filp)
  {
        struct file_lock *fl;
 -      struct inode *inode = locks_inode(filp);
 +      struct inode *inode = file_inode(filp);
        struct file_lock_context *ctx;
        int type = F_UNLCK;
        LIST_HEAD(dispose);
  static int
  check_conflicting_open(struct file *filp, const long arg, int flags)
  {
 -      struct inode *inode = locks_inode(filp);
 +      struct inode *inode = file_inode(filp);
        int self_wcount = 0, self_rcount = 0;
  
        if (flags & FL_LAYOUT)
@@@ -1704,7 -1703,7 +1704,7 @@@ static in
  generic_add_lease(struct file *filp, long arg, struct file_lock **flp, void **priv)
  {
        struct file_lock *fl, *my_fl = NULL, *lease;
 -      struct inode *inode = locks_inode(filp);
 +      struct inode *inode = file_inode(filp);
        struct file_lock_context *ctx;
        bool is_deleg = (*flp)->fl_flags & FL_DELEG;
        int error;
@@@ -1820,7 -1819,7 +1820,7 @@@ static int generic_delete_lease(struct 
  {
        int error = -EAGAIN;
        struct file_lock *fl, *victim = NULL;
 -      struct inode *inode = locks_inode(filp);
 +      struct inode *inode = file_inode(filp);
        struct file_lock_context *ctx;
        LIST_HEAD(dispose);
  
  int generic_setlease(struct file *filp, long arg, struct file_lock **flp,
                        void **priv)
  {
 -      struct inode *inode = locks_inode(filp);
 +      struct inode *inode = file_inode(filp);
        int error;
  
        if ((!uid_eq(current_fsuid(), inode->i_uid)) && !capable(CAP_LEASE))
  }
  EXPORT_SYMBOL(generic_setlease);
  
- #if IS_ENABLED(CONFIG_SRCU)
  /*
   * Kernel subsystems can register to be notified on any attempt to set
   * a new lease with the lease_notifier_chain. This is used by (e.g.) nfsd
@@@ -1924,30 -1922,6 +1923,6 @@@ void lease_unregister_notifier(struct n
  }
  EXPORT_SYMBOL_GPL(lease_unregister_notifier);
  
- #else /* !IS_ENABLED(CONFIG_SRCU) */
- static inline void
- lease_notifier_chain_init(void)
- {
- }
- static inline void
- setlease_notifier(long arg, struct file_lock *lease)
- {
- }
- int lease_register_notifier(struct notifier_block *nb)
- {
-       return 0;
- }
- EXPORT_SYMBOL_GPL(lease_register_notifier);
- void lease_unregister_notifier(struct notifier_block *nb)
- {
- }
- EXPORT_SYMBOL_GPL(lease_unregister_notifier);
- #endif /* IS_ENABLED(CONFIG_SRCU) */
  /**
   * vfs_setlease        -       sets a lease on an open file
   * @filp:     file pointer
@@@ -2351,7 -2325,7 +2326,7 @@@ int fcntl_setlk(unsigned int fd, struc
                struct flock *flock)
  {
        struct file_lock *file_lock = locks_alloc_lock();
 -      struct inode *inode = locks_inode(filp);
 +      struct inode *inode = file_inode(filp);
        struct file *f;
        int error;
  
@@@ -2555,7 -2529,7 +2530,7 @@@ out
  void locks_remove_posix(struct file *filp, fl_owner_t owner)
  {
        int error;
 -      struct inode *inode = locks_inode(filp);
 +      struct inode *inode = file_inode(filp);
        struct file_lock lock;
        struct file_lock_context *ctx;
  
@@@ -2592,7 -2566,7 +2567,7 @@@ static voi
  locks_remove_flock(struct file *filp, struct file_lock_context *flctx)
  {
        struct file_lock fl;
 -      struct inode *inode = locks_inode(filp);
 +      struct inode *inode = file_inode(filp);
  
        if (list_empty(&flctx->flc_flock))
                return;
@@@ -2637,7 -2611,7 +2612,7 @@@ void locks_remove_file(struct file *fil
  {
        struct file_lock_context *ctx;
  
 -      ctx = locks_inode_context(locks_inode(filp));
 +      ctx = locks_inode_context(file_inode(filp));
        if (!ctx)
                return;
  
@@@ -2721,7 -2695,7 +2696,7 @@@ static void lock_get_status(struct seq_
         */
  
        if (fl->fl_file != NULL)
 -              inode = locks_inode(fl->fl_file);
 +              inode = file_inode(fl->fl_file);
  
        seq_printf(f, "%lld: ", id);
  
@@@ -2862,7 -2836,7 +2837,7 @@@ static void __show_fd_locks(struct seq_
  void show_fd_locks(struct seq_file *f,
                  struct file *filp, struct files_struct *files)
  {
 -      struct inode *inode = locks_inode(filp);
 +      struct inode *inode = file_inode(filp);
        struct file_lock_context *ctx;
        int id = 0;
  
diff --combined init/Kconfig
index e76dc579cfa20364a22c3556bcfb0aa5ebf5a30e,af511c726d695db3b60c59874077055840868819..18f0bf50c4689bfc299adf23e55f1c75f769d8bd
@@@ -204,7 -204,7 +204,7 @@@ config LOCALVERSION_AUT
          appended after any matching localversion* files, and after the value
          set in CONFIG_LOCALVERSION.
  
 -        (The actual string used here is the first eight characters produced
 +        (The actual string used here is the first 12 characters produced
          by running the command:
  
            $ git rev-parse --verify HEAD
@@@ -776,7 -776,7 +776,7 @@@ config PRINTK_SAFE_LOG_BUF_SHIF
        depends on PRINTK
        help
          Select the size of an alternate printk per-CPU buffer where messages
 -        printed from usafe contexts are temporary stored. One example would
 +        printed from unsafe contexts are temporary stored. One example would
          be NMI messages, another one - printk recursion. The messages are
          copied to the main log buffer in a safe context to avoid a deadlock.
          The value defines the size as a power of 2.
@@@ -894,17 -894,13 +894,17 @@@ config CC_IMPLICIT_FALLTHROUG
        default "-Wimplicit-fallthrough=5" if CC_IS_GCC && $(cc-option,-Wimplicit-fallthrough=5)
        default "-Wimplicit-fallthrough" if CC_IS_CLANG && $(cc-option,-Wunreachable-code-fallthrough)
  
 -# Currently, disable gcc-12 array-bounds globally.
 +# Currently, disable gcc-11,12 array-bounds globally.
  # We may want to target only particular configurations some day.
 +config GCC11_NO_ARRAY_BOUNDS
 +      def_bool y
 +
  config GCC12_NO_ARRAY_BOUNDS
        def_bool y
  
  config CC_NO_ARRAY_BOUNDS
        bool
 +      default y if CC_IS_GCC && GCC_VERSION >= 110000 && GCC_VERSION < 120000 && GCC11_NO_ARRAY_BOUNDS
        default y if CC_IS_GCC && GCC_VERSION >= 120000 && GCC_VERSION < 130000 && GCC12_NO_ARRAY_BOUNDS
  
  #
@@@ -1045,10 -1041,6 +1045,10 @@@ config RT_GROUP_SCHE
  
  endif #CGROUP_SCHED
  
 +config SCHED_MM_CID
 +      def_bool y
 +      depends on SMP && RSEQ
 +
  config UCLAMP_TASK_GROUP
        bool "Utilization clamping per group of tasks"
        depends on CGROUP_SCHED
@@@ -1873,7 -1865,6 +1873,6 @@@ config PERF_EVENT
        default y if PROFILING
        depends on HAVE_PERF_EVENTS
        select IRQ_WORK
-       select SRCU
        help
          Enable kernel support for various performance events provided
          by software and hardware.
diff --combined kernel/sched/core.c
index fb49dbf6127353fcdde467ab61d5df0dae0bad9b,2e40a6c116e1c646ed08dfca839ea20fd2847fb0..af017e038b482f47b0783efe6c089b1c5c9bfab0
@@@ -152,7 -152,7 +152,7 @@@ __read_mostly int scheduler_running
  DEFINE_STATIC_KEY_FALSE(__sched_core_enabled);
  
  /* kernel prio, less is more */
 -static inline int __task_prio(struct task_struct *p)
 +static inline int __task_prio(const struct task_struct *p)
  {
        if (p->sched_class == &stop_sched_class) /* trumps deadline */
                return -2;
   */
  
  /* real prio, less is less */
 -static inline bool prio_less(struct task_struct *a, struct task_struct *b, bool in_fi)
 +static inline bool prio_less(const struct task_struct *a,
 +                           const struct task_struct *b, bool in_fi)
  {
  
        int pa = __task_prio(a), pb = __task_prio(b);
        return false;
  }
  
 -static inline bool __sched_core_less(struct task_struct *a, struct task_struct *b)
 +static inline bool __sched_core_less(const struct task_struct *a,
 +                                   const struct task_struct *b)
  {
        if (a->core_cookie < b->core_cookie)
                return true;
@@@ -2606,71 -2604,27 +2606,71 @@@ void do_set_cpus_allowed(struct task_st
                .user_mask = NULL,
                .flags     = SCA_USER,  /* clear the user requested mask */
        };
 +      union cpumask_rcuhead {
 +              cpumask_t cpumask;
 +              struct rcu_head rcu;
 +      };
  
        __do_set_cpus_allowed(p, &ac);
 -      kfree(ac.user_mask);
 +
 +      /*
 +       * Because this is called with p->pi_lock held, it is not possible
 +       * to use kfree() here (when PREEMPT_RT=y), therefore punt to using
 +       * kfree_rcu().
 +       */
 +      kfree_rcu((union cpumask_rcuhead *)ac.user_mask, rcu);
 +}
 +
 +static cpumask_t *alloc_user_cpus_ptr(int node)
 +{
 +      /*
 +       * See do_set_cpus_allowed() above for the rcu_head usage.
 +       */
 +      int size = max_t(int, cpumask_size(), sizeof(struct rcu_head));
 +
 +      return kmalloc_node(size, GFP_KERNEL, node);
  }
  
  int dup_user_cpus_ptr(struct task_struct *dst, struct task_struct *src,
                      int node)
  {
 +      cpumask_t *user_mask;
        unsigned long flags;
  
 -      if (!src->user_cpus_ptr)
 +      /*
 +       * Always clear dst->user_cpus_ptr first as their user_cpus_ptr's
 +       * may differ by now due to racing.
 +       */
 +      dst->user_cpus_ptr = NULL;
 +
 +      /*
 +       * This check is racy and losing the race is a valid situation.
 +       * It is not worth the extra overhead of taking the pi_lock on
 +       * every fork/clone.
 +       */
 +      if (data_race(!src->user_cpus_ptr))
                return 0;
  
 -      dst->user_cpus_ptr = kmalloc_node(cpumask_size(), GFP_KERNEL, node);
 -      if (!dst->user_cpus_ptr)
 +      user_mask = alloc_user_cpus_ptr(node);
 +      if (!user_mask)
                return -ENOMEM;
  
 -      /* Use pi_lock to protect content of user_cpus_ptr */
 +      /*
 +       * Use pi_lock to protect content of user_cpus_ptr
 +       *
 +       * Though unlikely, user_cpus_ptr can be reset to NULL by a concurrent
 +       * do_set_cpus_allowed().
 +       */
        raw_spin_lock_irqsave(&src->pi_lock, flags);
 -      cpumask_copy(dst->user_cpus_ptr, src->user_cpus_ptr);
 +      if (src->user_cpus_ptr) {
 +              swap(dst->user_cpus_ptr, user_mask);
 +              cpumask_copy(dst->user_cpus_ptr, src->user_cpus_ptr);
 +      }
        raw_spin_unlock_irqrestore(&src->pi_lock, flags);
 +
 +      if (unlikely(user_mask))
 +              kfree(user_mask);
 +
        return 0;
  }
  
@@@ -2953,11 -2907,8 +2953,11 @@@ static int __set_cpus_allowed_ptr_locke
        }
  
        if (!(ctx->flags & SCA_MIGRATE_ENABLE)) {
 -              if (cpumask_equal(&p->cpus_mask, ctx->new_mask))
 +              if (cpumask_equal(&p->cpus_mask, ctx->new_mask)) {
 +                      if (ctx->flags & SCA_USER)
 +                              swap(p->user_cpus_ptr, ctx->user_mask);
                        goto out;
 +              }
  
                if (WARN_ON_ONCE(p == current &&
                                 is_migration_disabled(p) &&
@@@ -3630,11 -3581,6 +3630,11 @@@ static inline bool rq_has_pinned_tasks(
        return false;
  }
  
 +static inline cpumask_t *alloc_user_cpus_ptr(int node)
 +{
 +      return NULL;
 +}
 +
  #endif /* !CONFIG_SMP */
  
  static void
@@@ -3677,39 -3623,14 +3677,39 @@@ ttwu_stat(struct task_struct *p, int cp
  }
  
  /*
 - * Mark the task runnable and perform wakeup-preemption.
 + * Mark the task runnable.
   */
 -static void ttwu_do_wakeup(struct rq *rq, struct task_struct *p, int wake_flags,
 -                         struct rq_flags *rf)
 +static inline void ttwu_do_wakeup(struct task_struct *p)
  {
 -      check_preempt_curr(rq, p, wake_flags);
        WRITE_ONCE(p->__state, TASK_RUNNING);
        trace_sched_wakeup(p);
 +}
 +
 +static void
 +ttwu_do_activate(struct rq *rq, struct task_struct *p, int wake_flags,
 +               struct rq_flags *rf)
 +{
 +      int en_flags = ENQUEUE_WAKEUP | ENQUEUE_NOCLOCK;
 +
 +      lockdep_assert_rq_held(rq);
 +
 +      if (p->sched_contributes_to_load)
 +              rq->nr_uninterruptible--;
 +
 +#ifdef CONFIG_SMP
 +      if (wake_flags & WF_MIGRATED)
 +              en_flags |= ENQUEUE_MIGRATED;
 +      else
 +#endif
 +      if (p->in_iowait) {
 +              delayacct_blkio_end(p);
 +              atomic_dec(&task_rq(p)->nr_iowait);
 +      }
 +
 +      activate_task(rq, p, en_flags);
 +      check_preempt_curr(rq, p, wake_flags);
 +
 +      ttwu_do_wakeup(p);
  
  #ifdef CONFIG_SMP
        if (p->sched_class->task_woken) {
  #endif
  }
  
 -static void
 -ttwu_do_activate(struct rq *rq, struct task_struct *p, int wake_flags,
 -               struct rq_flags *rf)
 -{
 -      int en_flags = ENQUEUE_WAKEUP | ENQUEUE_NOCLOCK;
 -
 -      lockdep_assert_rq_held(rq);
 -
 -      if (p->sched_contributes_to_load)
 -              rq->nr_uninterruptible--;
 -
 -#ifdef CONFIG_SMP
 -      if (wake_flags & WF_MIGRATED)
 -              en_flags |= ENQUEUE_MIGRATED;
 -      else
 -#endif
 -      if (p->in_iowait) {
 -              delayacct_blkio_end(p);
 -              atomic_dec(&task_rq(p)->nr_iowait);
 -      }
 -
 -      activate_task(rq, p, en_flags);
 -      ttwu_do_wakeup(rq, p, wake_flags, rf);
 -}
 -
  /*
   * Consider @p being inside a wait loop:
   *
@@@ -3772,15 -3718,9 +3772,15 @@@ static int ttwu_runnable(struct task_st
  
        rq = __task_rq_lock(p, &rf);
        if (task_on_rq_queued(p)) {
 -              /* check_preempt_curr() may use rq clock */
 -              update_rq_clock(rq);
 -              ttwu_do_wakeup(rq, p, wake_flags, &rf);
 +              if (!task_on_cpu(rq, p)) {
 +                      /*
 +                       * When on_rq && !on_cpu the task is preempted, see if
 +                       * it should preempt the task that is current now.
 +                       */
 +                      update_rq_clock(rq);
 +                      check_preempt_curr(rq, p, wake_flags);
 +              }
 +              ttwu_do_wakeup(p);
                ret = 1;
        }
        __task_rq_unlock(rq, &rf);
@@@ -4146,7 -4086,8 +4146,7 @@@ try_to_wake_up(struct task_struct *p, u
                        goto out;
  
                trace_sched_waking(p);
 -              WRITE_ONCE(p->__state, TASK_RUNNING);
 -              trace_sched_wakeup(p);
 +              ttwu_do_wakeup(p);
                goto out;
        }
  
@@@ -5111,7 -5052,6 +5111,7 @@@ prepare_task_switch(struct rq *rq, stru
        sched_info_switch(rq, prev, next);
        perf_event_task_sched_out(prev, next);
        rseq_preempt(prev);
 +      switch_mm_cid(prev, next);
        fire_sched_out_preempt_notifiers(prev, next);
        kmap_local_sched_out();
        prepare_task(next);
@@@ -5342,6 -5282,11 +5342,11 @@@ bool single_task_running(void
  }
  EXPORT_SYMBOL(single_task_running);
  
+ unsigned long long nr_context_switches_cpu(int cpu)
+ {
+       return cpu_rq(cpu)->nr_switches;
+ }
  unsigned long long nr_context_switches(void)
  {
        int i;
@@@ -5564,9 -5509,7 +5569,9 @@@ void scheduler_tick(void
        unsigned long thermal_pressure;
        u64 resched_latency;
  
 -      arch_scale_freq_tick();
 +      if (housekeeping_cpu(cpu, HK_TYPE_TICK))
 +              arch_scale_freq_tick();
 +
        sched_clock_tick();
  
        rq_lock(rq, &rf);
@@@ -6268,7 -6211,7 +6273,7 @@@ static bool steal_cookie_task(int cpu, 
  {
        int i;
  
 -      for_each_cpu_wrap(i, sched_domain_span(sd), cpu) {
 +      for_each_cpu_wrap(i, sched_domain_span(sd), cpu + 1) {
                if (i == cpu)
                        continue;
  
@@@ -8301,18 -8244,12 +8306,18 @@@ long sched_setaffinity(pid_t pid, cons
        if (retval)
                goto out_put_task;
  
 -      user_mask = kmalloc(cpumask_size(), GFP_KERNEL);
 -      if (!user_mask) {
 +      /*
 +       * With non-SMP configs, user_cpus_ptr/user_mask isn't used and
 +       * alloc_user_cpus_ptr() returns NULL.
 +       */
 +      user_mask = alloc_user_cpus_ptr(NUMA_NO_NODE);
 +      if (user_mask) {
 +              cpumask_copy(user_mask, in_mask);
 +      } else if (IS_ENABLED(CONFIG_SMP)) {
                retval = -ENOMEM;
                goto out_put_task;
        }
 -      cpumask_copy(user_mask, in_mask);
 +
        ac = (struct affinity_context){
                .new_mask  = in_mask,
                .user_mask = user_mask,
@@@ -11373,53 -11310,3 +11378,53 @@@ void call_trace_sched_update_nr_running
  {
          trace_sched_update_nr_running_tp(rq, count);
  }
 +
 +#ifdef CONFIG_SCHED_MM_CID
 +void sched_mm_cid_exit_signals(struct task_struct *t)
 +{
 +      struct mm_struct *mm = t->mm;
 +      unsigned long flags;
 +
 +      if (!mm)
 +              return;
 +      local_irq_save(flags);
 +      mm_cid_put(mm, t->mm_cid);
 +      t->mm_cid = -1;
 +      t->mm_cid_active = 0;
 +      local_irq_restore(flags);
 +}
 +
 +void sched_mm_cid_before_execve(struct task_struct *t)
 +{
 +      struct mm_struct *mm = t->mm;
 +      unsigned long flags;
 +
 +      if (!mm)
 +              return;
 +      local_irq_save(flags);
 +      mm_cid_put(mm, t->mm_cid);
 +      t->mm_cid = -1;
 +      t->mm_cid_active = 0;
 +      local_irq_restore(flags);
 +}
 +
 +void sched_mm_cid_after_execve(struct task_struct *t)
 +{
 +      struct mm_struct *mm = t->mm;
 +      unsigned long flags;
 +
 +      if (!mm)
 +              return;
 +      local_irq_save(flags);
 +      t->mm_cid = mm_cid_get(mm);
 +      t->mm_cid_active = 1;
 +      local_irq_restore(flags);
 +      rseq_set_notify_resume(t);
 +}
 +
 +void sched_mm_cid_fork(struct task_struct *t)
 +{
 +      WARN_ON_ONCE(!t->mm || t->mm_cid != -1);
 +      t->mm_cid_active = 1;
 +}
 +#endif
This page took 0.226044 seconds and 4 git commands to generate.