1 /*
2  * Copyright 2023 Linaro
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 
9 #define SLEEPTIME 10
10 #define STACKSIZE 1024
11 #define PRIORITY  7
12 
loop_0(void)13 void __no_optimization loop_0(void)
14 {
15 	/* Wait to spend some cycles */
16 	k_busy_wait(10);
17 }
18 
loop_1(void)19 void __no_optimization loop_1(void)
20 {
21 	/* Wait to spend some cycles */
22 	k_busy_wait(1000);
23 }
24 
25 /*
26  * 'main' thread can take its mutex promptly and run. 'thread_A' needs to wait 'main' give its
27  * (thread_A) mutex to run.
28  */
29 K_SEM_DEFINE(main_sem, 1, 1);		/* Initialized as ready to be taken */
30 K_SEM_DEFINE(thread_a_sem, 0, 1);	/* Initialized as already taken (blocked) */
31 
32 K_THREAD_STACK_DEFINE(thread_a_stack, STACKSIZE);
33 static struct k_thread thread_a_data;
34 
35 static int counter;
36 
get_sem_and_exec_function(struct k_sem * my_sem,struct k_sem * other_sem,void (* func)(void))37 void get_sem_and_exec_function(struct k_sem *my_sem, struct k_sem *other_sem, void (*func)(void))
38 {
39 	while (counter < 4) {
40 		k_sem_take(my_sem, K_FOREVER);
41 
42 		func();
43 		k_msleep(SLEEPTIME);
44 
45 		counter++;
46 		k_sem_give(other_sem);
47 	}
48 }
49 
thread_A(void * notused0,void * notused1,void * notused2)50 void thread_A(void *notused0, void *notused1, void *notused2)
51 {
52 	ARG_UNUSED(notused0);
53 	ARG_UNUSED(notused1);
54 	ARG_UNUSED(notused2);
55 
56 	get_sem_and_exec_function(&thread_a_sem, &main_sem, loop_0);
57 }
58 
main(void)59 int main(void)
60 {
61 	k_tid_t thread_a;
62 
63 	/* Create Thread A */
64 	thread_a = k_thread_create(&thread_a_data, thread_a_stack, STACKSIZE,
65 				   thread_A, NULL, NULL, NULL, PRIORITY, 0, K_NO_WAIT);
66 
67 	k_thread_name_set(thread_a, "thread_A");
68 
69 	/* Start ping-pong between 'main' and 'thread_A' */
70 	get_sem_and_exec_function(&main_sem, &thread_a_sem, loop_1);
71 
72 	return 0;
73 }
74