1 /*
2  * Copyright (c) 2018 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/ztest.h>
8 #include <zephyr/interrupt_util.h>
9 
10 #define DURATION	5
11 #define HANDLER_TOKEN	0xDEADBEEF
12 
13 /* Long enough to be guaranteed a tick "should have fired" */
14 #define TIMER_DELAY_US (128 * 1000000 / CONFIG_SYS_CLOCK_TICKS_PER_SEC)
15 
16 static struct k_timer irqlock_timer;
17 volatile uint32_t handler_result;
18 
timer_handler(struct k_timer * timer)19 static void timer_handler(struct k_timer *timer)
20 {
21 	ARG_UNUSED(timer);
22 	handler_result = HANDLER_TOKEN;
23 	printk("timer fired\n");
24 }
25 
26 /**
27  * @brief Test interrupt prevention
28  *
29  * @ingroup kernel_interrupt_tests
30  *
31  * This routine tests if the kernel is capable of preventing interruption, by
32  * locking interrupts and busy-waiting to see if the system timer interrupt is
33  * serviced while interrupts are locked; in addition, this test also verifies
34  * that the system timer interrupt is serviced after interrupts are unlocked.
35  */
ZTEST(interrupt_feature,test_prevent_interruption)36 ZTEST(interrupt_feature, test_prevent_interruption)
37 {
38 	unsigned int key;
39 
40 	printk("locking interrupts\n");
41 	key = irq_lock();
42 
43 	handler_result = 0;
44 
45 	k_timer_init(&irqlock_timer, timer_handler, NULL);
46 
47 	/* Start the timer and busy-wait for a bit with IRQs locked. The
48 	 * timer ought to have fired during this time if interrupts weren't
49 	 * locked -- but since they are, check_lock_new isn't updated.
50 	 */
51 	k_timer_start(&irqlock_timer, K_MSEC(DURATION), K_NO_WAIT);
52 	k_busy_wait(TIMER_DELAY_US);
53 	zassert_not_equal(handler_result, HANDLER_TOKEN,
54 		"timer interrupt was serviced while interrupts are locked");
55 
56 	printk("unlocking interrupts\n");
57 	irq_unlock(key);
58 
59 	k_busy_wait(TIMER_DELAY_US);
60 
61 	zassert_equal(handler_result, HANDLER_TOKEN,
62 		"timer should have fired");
63 
64 	k_timer_stop(&irqlock_timer);
65 }
66 
67 ZTEST_SUITE(interrupt_feature, NULL, NULL, NULL, NULL, NULL);
68