@@ -20,8 +20,8 @@ struct kunit_irq_test_state {
2020 bool task_func_reported_failure ;
2121 bool hardirq_func_reported_failure ;
2222 bool softirq_func_reported_failure ;
23- unsigned long hardirq_func_calls ;
24- unsigned long softirq_func_calls ;
23+ atomic_t hardirq_func_calls ;
24+ atomic_t softirq_func_calls ;
2525 struct hrtimer timer ;
2626 struct work_struct bh_work ;
2727};
@@ -32,7 +32,7 @@ static enum hrtimer_restart kunit_irq_test_timer_func(struct hrtimer *timer)
3232 container_of (timer , typeof (* state ), timer );
3333
3434 WARN_ON_ONCE (!in_hardirq ());
35- state -> hardirq_func_calls ++ ;
35+ atomic_inc ( & state -> hardirq_func_calls ) ;
3636
3737 if (!state -> func (state -> test_specific_state ))
3838 state -> hardirq_func_reported_failure = true;
@@ -48,7 +48,7 @@ static void kunit_irq_test_bh_work_func(struct work_struct *work)
4848 container_of (work , typeof (* state ), bh_work );
4949
5050 WARN_ON_ONCE (!in_serving_softirq ());
51- state -> softirq_func_calls ++ ;
51+ atomic_inc ( & state -> softirq_func_calls ) ;
5252
5353 if (!state -> func (state -> test_specific_state ))
5454 state -> softirq_func_reported_failure = true;
@@ -59,7 +59,10 @@ static void kunit_irq_test_bh_work_func(struct work_struct *work)
5959 * hardirq context concurrently, and reports a failure to KUnit if any
6060 * invocation of @func in any context returns false. @func is passed
6161 * @test_specific_state as its argument. At most 3 invocations of @func will
62- * run concurrently: one in each of task, softirq, and hardirq context.
62+ * run concurrently: one in each of task, softirq, and hardirq context. @func
63+ * will continue running until either @max_iterations calls have been made (so
64+ * long as at least one each runs in task, softirq, and hardirq contexts), or
65+ * one second has passed.
6366 *
6467 * The main purpose of this interrupt context testing is to validate fallback
6568 * code paths that run in contexts where the normal code path cannot be used,
@@ -85,6 +88,8 @@ static inline void kunit_run_irq_test(struct kunit *test, bool (*func)(void *),
8588 .test_specific_state = test_specific_state ,
8689 };
8790 unsigned long end_jiffies ;
91+ int hardirq_calls , softirq_calls ;
92+ bool allctx = false;
8893
8994 /*
9095 * Set up a hrtimer (the way we access hardirq context) and a work
@@ -94,36 +99,44 @@ static inline void kunit_run_irq_test(struct kunit *test, bool (*func)(void *),
9499 CLOCK_MONOTONIC , HRTIMER_MODE_REL_HARD );
95100 INIT_WORK_ONSTACK (& state .bh_work , kunit_irq_test_bh_work_func );
96101
97- /* Run for up to max_iterations or 1 second, whichever comes first. */
102+ /*
103+ * Run for up to max_iterations (including at least one task, softirq,
104+ * and hardirq), or 1 second, whichever comes first.
105+ */
98106 end_jiffies = jiffies + HZ ;
99107 hrtimer_start (& state .timer , KUNIT_IRQ_TEST_HRTIMER_INTERVAL ,
100108 HRTIMER_MODE_REL_HARD );
101- for (int i = 0 ; i < max_iterations && !time_after (jiffies , end_jiffies );
102- i ++ ) {
109+ for (int task_calls = 0 , calls = 0 ;
110+ ((calls < max_iterations ) || !allctx ) &&
111+ !time_after (jiffies , end_jiffies );
112+ task_calls ++ ) {
103113 if (!func (test_specific_state ))
104114 state .task_func_reported_failure = true;
115+
116+ hardirq_calls = atomic_read (& state .hardirq_func_calls );
117+ softirq_calls = atomic_read (& state .softirq_func_calls );
118+ calls = task_calls + hardirq_calls + softirq_calls ;
119+ allctx = (task_calls > 0 ) && (hardirq_calls > 0 ) &&
120+ (softirq_calls > 0 );
105121 }
106122
107123 /* Cancel the timer and work. */
108124 hrtimer_cancel (& state .timer );
109125 flush_work (& state .bh_work );
110126
111127 /* Sanity check: the timer and BH functions should have been run. */
112- KUNIT_EXPECT_GT_MSG (test , state .hardirq_func_calls , 0 ,
128+ KUNIT_EXPECT_GT_MSG (test , atomic_read ( & state .hardirq_func_calls ) , 0 ,
113129 "Timer function was not called" );
114- KUNIT_EXPECT_GT_MSG (test , state .softirq_func_calls , 0 ,
130+ KUNIT_EXPECT_GT_MSG (test , atomic_read ( & state .softirq_func_calls ) , 0 ,
115131 "BH work function was not called" );
116132
117- /* Check for incorrect hash values reported from any context. */
118- KUNIT_EXPECT_FALSE_MSG (
119- test , state .task_func_reported_failure ,
120- "Incorrect hash values reported from task context" );
121- KUNIT_EXPECT_FALSE_MSG (
122- test , state .hardirq_func_reported_failure ,
123- "Incorrect hash values reported from hardirq context" );
124- KUNIT_EXPECT_FALSE_MSG (
125- test , state .softirq_func_reported_failure ,
126- "Incorrect hash values reported from softirq context" );
133+ /* Check for failure reported from any context. */
134+ KUNIT_EXPECT_FALSE_MSG (test , state .task_func_reported_failure ,
135+ "Failure reported from task context" );
136+ KUNIT_EXPECT_FALSE_MSG (test , state .hardirq_func_reported_failure ,
137+ "Failure reported from hardirq context" );
138+ KUNIT_EXPECT_FALSE_MSG (test , state .softirq_func_reported_failure ,
139+ "Failure reported from softirq context" );
127140}
128141
129142#endif /* _KUNIT_RUN_IN_IRQ_CONTEXT_H */
0 commit comments