aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrederic Weisbecker <frederic@kernel.org>2024-02-16 16:28:30 +0100
committerFrederic Weisbecker <frederic@kernel.org>2024-02-19 13:11:30 +0100
commit7e5666358c1b4b38fe229e1f75fa2a211d60f3f0 (patch)
tree32621d45d65266f1318767ba0cd534288ff42dee
parent35562ef99e4c3453ffe2a2215d1fac40891e0412 (diff)
downloadlinux-dynticks-timers/anna-experimental.tar.gz
Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
-rw-r--r--include/linux/sched.h6
-rw-r--r--kernel/rcu/rcutorture.c12
-rw-r--r--kernel/time/timer.c53
-rw-r--r--kernel/time/timer_migration.c4
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm.sh2
5 files changed, 57 insertions, 20 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h
index ffe8f618ab8697..47c83cdedbbd45 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -745,6 +745,11 @@ struct kmap_ctrl {
#endif
};
+struct process_timer {
+ struct timer_list timer;
+ struct task_struct *task;
+};
+
struct task_struct {
#ifdef CONFIG_THREAD_INFO_IN_TASK
/*
@@ -1546,6 +1551,7 @@ struct task_struct {
#ifdef CONFIG_USER_EVENTS
struct user_event_mm *user_event_mm;
#endif
+ struct process_timer process_timer;
/*
* New fields for task_struct should be added above here, so that
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 7567ca8e743ca6..e14bf78c42a55f 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -335,6 +335,8 @@ rcu_torture_free(struct rcu_torture *p)
spin_unlock_bh(&rcu_torture_lock);
}
+void timers_dump_cpu(unsigned int cpu);
+
/*
* Operations vector for selecting different types of tests.
*/
@@ -1361,7 +1363,7 @@ rcu_torture_writer(void *arg)
unsigned long gp_snap1;
struct rcu_gp_oldstate gp_snap_full;
struct rcu_gp_oldstate gp_snap1_full;
- int i;
+ int i, j;
int idx;
int oldnice = task_nice(current);
struct rcu_gp_oldstate rgo[NUM_ACTIVE_RCU_POLL_FULL_OLDSTATE];
@@ -1584,6 +1586,9 @@ rcu_torture_writer(void *arg)
tracing_off();
show_rcu_gp_kthreads();
WARN(1, "%s: rtort_pipe_count: %d\n", __func__, rcu_tortures[i].rtort_pipe_count);
+ for_each_online_cpu(j) {
+ timers_dump_cpu(j);
+ }
rcu_ftrace_dump(DUMP_ALL);
}
if (stutter_waited)
@@ -2168,7 +2173,7 @@ static void
rcu_torture_stats_print(void)
{
int cpu;
- int i;
+ int i, j;
long pipesummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 };
long batchsummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 };
struct rcu_torture *rtcp;
@@ -2271,6 +2276,9 @@ rcu_torture_stats_print(void)
}
if (cur_ops->gp_kthread_dbg)
cur_ops->gp_kthread_dbg();
+ for_each_online_cpu(j) {
+ timers_dump_cpu(j);
+ }
rcu_ftrace_dump(DUMP_ALL);
}
rtcv_snap = rcu_torture_current_version;
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 320eb4ceafa2b5..64ce9a7760f595 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -616,7 +616,8 @@ static void enqueue_timer(struct timer_base *base, struct timer_list *timer,
__set_bit(idx, base->pending_map);
timer_set_idx(timer, idx);
- trace_timer_start(timer, bucket_expiry);
+ if (!(timer->flags & TIMER_PINNED))
+ trace_timer_start(timer, bucket_expiry);
/*
* Check whether this is the new first expiring timer. The
@@ -838,8 +839,9 @@ static inline void debug_init(struct timer_list *timer)
static inline void debug_deactivate(struct timer_list *timer)
{
- debug_timer_deactivate(timer);
- trace_timer_cancel(timer);
+ debug_timer_deactivate(timer);
+ if (!(timer->flags & TIMER_PINNED))
+ trace_timer_cancel(timer);
}
static inline void debug_assert_init(struct timer_list *timer)
@@ -1744,7 +1746,8 @@ static void call_timer_fn(struct timer_list *timer,
*/
lock_map_acquire(&lockdep_map);
- trace_timer_expire_entry(timer, baseclk);
+ if (!(timer->flags & TIMER_PINNED))
+ trace_timer_expire_entry(timer, baseclk);
fn(timer);
trace_timer_expire_exit(timer);
@@ -2004,6 +2007,8 @@ static unsigned long fetch_next_timer_interrupt(unsigned long basej, u64 basem,
if (time_before(nextevt, basej))
nextevt = basej;
tevt->local = basem + (u64)(nextevt - basej) * TICK_NSEC;
+ if (!local_first)
+ tevt->global = tevt->local;
return nextevt;
}
@@ -2428,10 +2433,6 @@ void update_process_times(int user_tick)
* Since schedule_timeout()'s timer is defined on the stack, it must store
* the target task on the stack as well.
*/
-struct process_timer {
- struct timer_list timer;
- struct task_struct *task;
-};
static void process_timeout(struct timer_list *t)
{
@@ -2473,7 +2474,7 @@ static void process_timeout(struct timer_list *t)
*/
signed long __sched schedule_timeout(signed long timeout)
{
- struct process_timer timer;
+ struct process_timer *timer = &current->process_timer;
unsigned long expire;
switch (timeout)
@@ -2507,14 +2508,11 @@ signed long __sched schedule_timeout(signed long timeout)
expire = timeout + jiffies;
- timer.task = current;
- timer_setup_on_stack(&timer.timer, process_timeout, 0);
- __mod_timer(&timer.timer, expire, MOD_TIMER_NOTPENDING);
+ timer->task = current;
+ timer_setup(&timer->timer, process_timeout, 0);
+ __mod_timer(&timer->timer, expire, MOD_TIMER_NOTPENDING);
schedule();
- del_timer_sync(&timer.timer);
-
- /* Remove the timer from the object tracker */
- destroy_timer_on_stack(&timer.timer);
+ del_timer_sync(&timer->timer);
timeout = expire - jiffies;
@@ -2624,6 +2622,29 @@ int timers_dead_cpu(unsigned int cpu)
return 0;
}
+void timers_dump_cpu(unsigned int cpu);
+
+void timers_dump_cpu(unsigned int cpu)
+{
+ struct timer_base *base = per_cpu_ptr(&timer_bases[BASE_GLOBAL], cpu);
+ unsigned long flags;
+ int i;
+
+ printk("Dumping CPU timers for %d\n", cpu);
+ raw_spin_lock_irqsave(&base->lock, flags);
+ for (i = 0; i < WHEEL_SIZE; i++) {
+ struct timer_list *t;
+
+ hlist_for_each_entry(t, base->vectors + i, entry) {
+ if (t->expires < jiffies)
+ printk("CPU: %d timer:%p func=%ps expires=%lu now=%lu diff=%lu\n", cpu, t, t->function, t->expires, jiffies, jiffies - t->expires);
+ }
+ }
+ raw_spin_unlock_irqrestore(&base->lock, flags);
+}
+EXPORT_SYMBOL(timers_dump_cpu);
+
+
#endif /* CONFIG_HOTPLUG_CPU */
static void __init init_timer_cpu(int cpu)
diff --git a/kernel/time/timer_migration.c b/kernel/time/timer_migration.c
index b1a27e9a6db4b2..437db316aa3219 100644
--- a/kernel/time/timer_migration.c
+++ b/kernel/time/timer_migration.c
@@ -977,7 +977,7 @@ static void tmigr_handle_remote_cpu(unsigned int cpu, u64 now,
* after a remote expiry" in the documentation at the top)
*/
walk_groups(&tmigr_new_timer_up, &data, tmc);
-
+ trace_tmigr_cpu_new_timer_idle(tmc, tevt.global);
unlock:
tmc->remote = false;
raw_spin_unlock_irq(&tmc->lock);
@@ -1017,6 +1017,8 @@ again:
if (evt) {
unsigned int remote_cpu = evt->cpu;
+// if (now > evt->nextevt.expires + 1)
+// trace_printk("Handle late CPU=%u now=%llu expires=%llu delta=%llu\n", remote_cpu, now, evt->nextevt.expires, now - evt->nextevt.expires);
raw_spin_unlock_irq(&group->lock);
tmigr_handle_remote_cpu(remote_cpu, now, jif);
diff --git a/tools/testing/selftests/rcutorture/bin/kvm.sh b/tools/testing/selftests/rcutorture/bin/kvm.sh
index 7af73ddc148d1d..b8e41ed4673c57 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm.sh
@@ -42,7 +42,7 @@ TORTURE_JITTER_STOP=""
TORTURE_KCONFIG_KASAN_ARG=""
TORTURE_KCONFIG_KCSAN_ARG=""
TORTURE_KMAKE_ARG=""
-TORTURE_QEMU_MEM=512
+TORTURE_QEMU_MEM=1024
torture_qemu_mem_default=1
TORTURE_REMOTE=
TORTURE_SHUTDOWN_GRACE=180