1 /*
2  * Copyright (c) 2020 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/internal/syscall_handler.h>
9 
10 #include "footprint.h"
11 
12 static struct k_work_q workq;
13 static K_THREAD_STACK_DEFINE(workq_stack, STACK_SIZE);
14 
15 struct k_sem sync_sema;
16 
17 #if CONFIG_USERSPACE
18 static struct k_work_user_q user_workq;
19 static K_THREAD_STACK_DEFINE(user_workq_stack, STACK_SIZE);
20 
21 static FP_BMEM struct k_work_user user_work_item;
22 
user_workq_func(struct k_work_user * unused)23 void user_workq_func(struct k_work_user *unused)
24 {
25 	ARG_UNUSED(unused);
26 
27 	k_sem_give(&sync_sema);
28 }
29 
30 #endif
31 
workq_func(struct k_work * unused)32 void workq_func(struct k_work *unused)
33 {
34 	ARG_UNUSED(unused);
35 
36 	k_sem_give(&sync_sema);
37 }
38 
simple_workq_thread(void * arg1,void * arg2,void * arg3)39 void simple_workq_thread(void *arg1, void *arg2, void *arg3)
40 {
41 	struct k_work work_item;
42 
43 	ARG_UNUSED(arg1);
44 	ARG_UNUSED(arg2);
45 	ARG_UNUSED(arg3);
46 
47 	k_sem_reset(&sync_sema);
48 	k_work_init(&work_item, workq_func);
49 	k_work_submit_to_queue(&workq, &work_item);
50 
51 	k_sem_take(&sync_sema, K_FOREVER);
52 }
53 
delayed_workq_thread(void * arg1,void * arg2,void * arg3)54 void delayed_workq_thread(void *arg1, void *arg2, void *arg3)
55 {
56 	struct k_work_delayable work_item;
57 
58 	ARG_UNUSED(arg1);
59 	ARG_UNUSED(arg2);
60 	ARG_UNUSED(arg3);
61 
62 	k_sem_reset(&sync_sema);
63 	k_work_init_delayable(&work_item, workq_func);
64 	k_work_reschedule_for_queue(&workq, &work_item, K_NO_WAIT);
65 
66 	k_sem_take(&sync_sema, K_FOREVER);
67 }
68 
69 #if CONFIG_USERSPACE
simple_user_workq_thread(void * arg1,void * arg2,void * arg3)70 void simple_user_workq_thread(void *arg1, void *arg2, void *arg3)
71 {
72 	ARG_UNUSED(arg1);
73 	ARG_UNUSED(arg2);
74 	ARG_UNUSED(arg3);
75 
76 	k_sem_reset(&sync_sema);
77 	k_work_user_init(&user_work_item, user_workq_func);
78 	k_work_user_submit_to_queue(&user_workq, &user_work_item);
79 
80 	k_sem_take(&sync_sema, K_FOREVER);
81 }
82 #endif
83 
run_workq(void)84 void run_workq(void)
85 {
86 	k_tid_t tid;
87 
88 	k_sem_init(&sync_sema, 0, 1);
89 
90 	k_work_queue_start(&workq, workq_stack,
91 			   K_THREAD_STACK_SIZEOF(workq_stack),
92 			   CONFIG_MAIN_THREAD_PRIORITY, NULL);
93 
94 	/* Exercise simple workqueue */
95 	tid = k_thread_create(&my_thread, my_stack_area, STACK_SIZE,
96 			      simple_workq_thread, NULL, NULL, NULL,
97 			      0, 0, K_NO_WAIT);
98 
99 	k_thread_join(tid, K_FOREVER);
100 
101 	/* Exercise delayed workqueue */
102 	tid = k_thread_create(&my_thread, my_stack_area, STACK_SIZE,
103 			      delayed_workq_thread, NULL, NULL, NULL,
104 			      0, 0, K_NO_WAIT);
105 
106 	k_thread_join(tid, K_FOREVER);
107 
108 #if CONFIG_USERSPACE
109 	k_work_user_queue_start(&user_workq, user_workq_stack,
110 				K_THREAD_STACK_SIZEOF(user_workq_stack),
111 				CONFIG_MAIN_THREAD_PRIORITY, NULL);
112 
113 	/* The work queue thread has been started, but it's OK because
114 	 * it doesn't need these permissions until something's submitted
115 	 * to it.
116 	 */
117 	k_mem_domain_add_thread(&footprint_mem_domain, &user_workq.thread);
118 	k_thread_access_grant(&user_workq.thread, &sync_sema);
119 
120 	tid = k_thread_create(&my_thread, my_stack_area, STACK_SIZE,
121 			      simple_user_workq_thread, NULL, NULL, NULL,
122 			      0, K_USER, K_FOREVER);
123 
124 	k_thread_access_grant(tid, &sync_sema,
125 			      &user_workq.thread, &user_workq.queue,
126 			      &user_workq_stack);
127 
128 	k_mem_domain_add_thread(&footprint_mem_domain, tid);
129 
130 	k_thread_start(tid);
131 	k_thread_join(tid, K_FOREVER);
132 
133 #endif
134 }
135