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