@@ -56,10 +56,14 @@ static const struct module_interface userspace_proxy_interface;
5656
5757static inline int user_worker_get (int cpu )
5858{
59+ ARG_UNUSED (cpu );
5960 return 0 ;
6061}
6162
62- static inline void user_worker_put (int cpu ) { }
63+ static inline void user_worker_put (int cpu )
64+ {
65+ ARG_UNUSED (cpu );
66+ }
6367
6468struct k_work_user * userspace_proxy_register_ipc_handler (struct processing_module * mod ,
6569 struct k_event * event )
@@ -86,9 +90,10 @@ struct k_work_user *userspace_proxy_register_ipc_handler(struct processing_modul
8690 * It invokes the appropriate module function in userspace context and writes the operation
8791 * result back into the work item.
8892 *
89- * There is only a single work queue, which is shared by all userspace modules. It is created
90- * dynamically when needed. Because SOF uses a single dedicated thread for handling IPC, there
91- * is no need to perform any additional serialization when accessing the worker.
93+ * There is a separate work queue per core. Each core's work queue is shared by all
94+ * userspace modules running on that core and is created dynamically when needed. A given
95+ * core's worker is only accessed from that same core's IPC handling context, so there is no
96+ * need to perform any additional serialization when accessing it.
9297 */
9398struct user_worker {
9499 k_tid_t thread_id ; /* ipc worker thread ID */
@@ -100,36 +105,17 @@ struct user_worker {
100105
101106static struct user_worker worker [CONFIG_CORE_COUNT ];
102107
103- #if 0
104- static void sof_work_user_queue_init (struct k_work_user_q * work_q , k_thread_stack_t * stack ,
105- size_t stack_size , int prio , const char * name )
106- {
107- k_queue_init (& work_q -> queue );
108-
109- /* Created worker thread will inherit object permissions and memory
110- * domain configuration of the caller
111- */
112- k_thread_create (& work_q -> thread , stack , stack_size , z_work_user_q_main ,
113- work_q , NULL , NULL , prio , K_USER | K_INHERIT_PERMS ,
114- K_FOREVER );
115- k_object_access_grant (& work_q -> queue , & work_q -> thread );
116- if (name != NULL ) {
117- k_thread_name_set (& work_q -> thread , name );
118- }
119-
120- ///k_thread_start(&work_q->thread);
121- }
122- #endif // 0
123-
124108static int user_worker_get (int cpu )
125109{
110+ assert (cpu >= 0 && cpu < (int )ARRAY_SIZE (worker ));
111+
126112 if (worker [cpu ].reference_count ) {
127113 worker [cpu ].reference_count ++ ;
128114 return 0 ;
129115 }
130116
131117 worker [cpu ].stack_ptr = user_stack_allocate (CONFIG_SOF_USERSPACE_PROXY_WORKER_STACK_SIZE ,
132- K_USER );
118+ K_USER );
133119 if (!worker [cpu ].stack_ptr ) {
134120 tr_err (& userspace_proxy_tr , "Userspace worker stack allocation failed." );
135121 return - ENOMEM ;
@@ -141,6 +127,10 @@ static int user_worker_get(int cpu)
141127
142128 worker [cpu ].thread_id = k_work_user_queue_thread_get (& worker [cpu ].work_queue );
143129
130+ /*
131+ * k_work_user_queue_start() starts the worker thread immediately.
132+ * We need to make sure it is not running when pinning it to a specific core.
133+ */
144134 k_thread_suspend (worker [cpu ].thread_id );
145135
146136 /* Pin worker thread to the same core as the module */
@@ -157,6 +147,8 @@ static int user_worker_get(int cpu)
157147
158148static void user_worker_put (int cpu )
159149{
150+ assert (cpu >= 0 && cpu < (int )ARRAY_SIZE (worker ));
151+
160152 /* Module removed so decrement counter */
161153 worker [cpu ].reference_count -- ;
162154
@@ -178,10 +170,7 @@ static int user_work_item_init(struct userspace_context *user_ctx, struct k_heap
178170 if (ret )
179171 return ret ;
180172
181- /* We have only a single userspace IPC worker. It handles requests for all userspace
182- * modules, which may run on different cores. Because the worker processes work items
183- * coming from any core, the work item must be allocated in coherent memory.
184- */
173+ /* TODO: this can probably be allocated as cached? */
185174 work_item = sof_heap_alloc (user_heap , SOF_MEM_FLAG_COHERENT , sizeof (* work_item ), 0 );
186175 if (!work_item ) {
187176 user_worker_put (cpu );
@@ -253,17 +242,6 @@ static int userspace_proxy_invoke(struct userspace_context *user_ctx, uint32_t c
253242 goto done ;
254243 }
255244
256- #if 0
257- #ifdef CONFIG_SCHED_CPU_MASK
258- /* Pin worker thread to the same core as the module */
259- ret = k_thread_cpu_pin (worker [cpu ].thread_id , cpu );
260- if (ret < 0 ) {
261- tr_err (& userspace_proxy_tr , "Failed to pin cpu, error: %d" , ret );
262- goto done ;
263- }
264- #endif
265- #endif // 0
266-
267245 ret = k_work_user_submit_to_queue (& worker [cpu ].work_queue , & user_ctx -> work_item -> work_item );
268246 if (ret < 0 ) {
269247 tr_err (& userspace_proxy_tr , "Submit to queue error: %d" , ret );
0 commit comments