1 /*
2  * Copyright (c) 2017 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/ztest.h>
8 #include "test_sched.h"
9 
10 /* nrf 51 has lower ram, so creating less number of threads */
11 #if CONFIG_SRAM_SIZE <= 24
12 	#define NUM_THREAD 2
13 #elif (CONFIG_SRAM_SIZE <= 32) \
14 	|| defined(CONFIG_SOC_EMSK_EM7D)
15 	#define NUM_THREAD 3
16 #else
17 	#define NUM_THREAD 10
18 #endif
19 #define ITERATION_COUNT 5
20 #define BASE_PRIORITY 1
21 
22 BUILD_ASSERT(NUM_THREAD <= MAX_NUM_THREAD);
23 
24 /* Semaphore on which Ztest thread wait */
25 static K_SEM_DEFINE(sema2, 0, NUM_THREAD);
26 
27 /* Semaphore on which application threads wait */
28 static K_SEM_DEFINE(sema3, 0, NUM_THREAD);
29 
30 static int thread_idx;
31 static struct k_thread t[NUM_THREAD];
32 
33 /* Application thread */
thread_tslice(void * p1,void * p2,void * p3)34 static void thread_tslice(void *p1, void *p2, void *p3)
35 {
36 	int idx = POINTER_TO_INT(p1);
37 
38 	/* Print New line for last thread */
39 	int thread_parameter = (idx == (NUM_THREAD - 1)) ? '\n' :
40 			       (idx + 'A');
41 
42 	while (1) {
43 		/* Printing alphabet corresponding to thread */
44 		TC_PRINT("%c", thread_parameter);
45 		/* Testing if threads are executed as per priority */
46 		zassert_true((idx == thread_idx));
47 		thread_idx = (thread_idx + 1) % (NUM_THREAD);
48 
49 		/* Release CPU and give chance to Ztest thread to run */
50 		k_sem_give(&sema2);
51 		/* Wait for release of semaphore from Ztest thread */
52 		k_sem_take(&sema3, K_FOREVER);
53 	}
54 
55 }
56 
57 /* test cases */
58 
59 /**
60  * @brief Check the behavior of preemptive threads with different priorities
61  *
62  * @details Create multiple threads of different priorities - all are preemptive,
63  * current thread is also made preemptive. Check how the threads get chance to
64  * execute based on their priorities
65  *
66  * @ingroup kernel_sched_tests
67  */
ZTEST(threads_scheduling,test_priority_scheduling)68 ZTEST(threads_scheduling, test_priority_scheduling)
69 {
70 	k_tid_t tid[NUM_THREAD];
71 	int old_prio = k_thread_priority_get(k_current_get());
72 	int count = 0;
73 
74 	/* update priority for current thread */
75 	k_thread_priority_set(k_current_get(),
76 			      K_PRIO_PREEMPT(BASE_PRIORITY - 1));
77 
78 	/* Create Threads with different Priority */
79 	for (int i = 0; i < NUM_THREAD; i++) {
80 		tid[i] = k_thread_create(&t[i], tstacks[i], STACK_SIZE,
81 					 thread_tslice, INT_TO_POINTER(i), NULL, NULL,
82 					 K_PRIO_PREEMPT(BASE_PRIORITY + i), 0,
83 					 K_NO_WAIT);
84 	}
85 
86 	while (count < ITERATION_COUNT) {
87 
88 		/* Wait for each thread to complete */
89 		for (int i = 0; i < NUM_THREAD; i++) {
90 			k_sem_take(&sema2, K_FOREVER);
91 		}
92 		/* Delay to give chance to last thread to run */
93 		k_sleep(K_MSEC(1));
94 
95 		/* Giving Chance to other threads to run */
96 		for (int i = 0; i < NUM_THREAD; i++) {
97 			k_sem_give(&sema3);
98 		}
99 		count++;
100 	}
101 
102 
103 	/* test case teardown */
104 	for (int i = 0; i < NUM_THREAD; i++) {
105 		k_thread_abort(tid[i]);
106 	}
107 	/* Set priority of Main thread to its old value */
108 	k_thread_priority_set(k_current_get(), old_prio);
109 }
110