@@ -41,7 +41,10 @@ struct zephyr_ll {
4141struct zephyr_ll_pdata {
4242 bool run ;
4343 bool freeing ;
44+ struct k_sem * sem_p ;
45+ #if !CONFIG_DYNAMIC_OBJECTS
4446 struct k_sem sem ;
47+ #endif
4548};
4649
4750#if CONFIG_SOF_USERSPACE_LL
@@ -136,7 +139,7 @@ static void zephyr_ll_task_done(struct zephyr_ll *sch,
136139 * zephyr_ll_task_free() is trying to free this task. Complete
137140 * it and signal the semaphore to let the function proceed
138141 */
139- k_sem_give (& pdata -> sem );
142+ k_sem_give (pdata -> sem_p );
140143
141144 tr_info (& ll_tr , "task complete %p %pU" , task , task -> uid );
142145 tr_info (& ll_tr , "num_tasks %d total_num_tasks %ld" ,
@@ -448,6 +451,98 @@ static int zephyr_ll_task_schedule_after(void *data, struct task *task, uint64_t
448451 return zephyr_ll_task_schedule_common (sch , task , start , period , after , false);
449452}
450453
454+ #if CONFIG_DYNAMIC_OBJECTS
455+ static struct list_item zephyr_ll_task_sem_list = LIST_INIT (zephyr_ll_task_sem_list );
456+
457+ struct zephyr_ll_task_sem {
458+ struct task * task ;
459+ struct k_sem * sem ;
460+ struct list_item list ;
461+ };
462+
463+ int z_impl_zephyr_ll_task_sem_alloc (struct task * task )
464+ {
465+ struct zephyr_ll_pdata * pdata = task -> priv_data ;
466+ struct zephyr_ll_task_sem * ts = rmalloc (SOF_MEM_FLAG_COHERENT , sizeof (* ts ));
467+
468+ if (!ts )
469+ return - ENOMEM ;
470+
471+ ts -> sem = k_object_alloc (K_OBJ_SEM );
472+ if (!ts -> sem ) {
473+ rfree (ts );
474+ return - ENOMEM ;
475+ }
476+
477+ k_sem_init (ts -> sem , 0 , 1 );
478+
479+ ts -> task = task ;
480+ pdata -> sem_p = ts -> sem ;
481+ /* List is protected by IPC serialization */
482+ list_item_append (& ts -> list , & zephyr_ll_task_sem_list );
483+
484+ return 0 ;
485+ }
486+
487+ int z_impl_zephyr_ll_task_sem_free (struct task * task )
488+ {
489+ struct zephyr_ll_pdata * pdata = task -> priv_data ;
490+ struct list_item * list ;
491+ struct zephyr_ll_task_sem * ts ;
492+ bool found = false;
493+
494+ /* List is protected by IPC serialization */
495+ list_for_item (list , & zephyr_ll_task_sem_list ) {
496+ ts = container_of (list , struct zephyr_ll_task_sem , list );
497+ if (ts -> task == task ) {
498+ found = true;
499+ break ;
500+ }
501+ }
502+
503+ if (!found )
504+ return - ENOENT ;
505+
506+ if (pdata -> sem_p != ts -> sem )
507+ return - EINVAL ;
508+
509+ list_item_del (list );
510+ k_object_free (ts -> sem );
511+ rfree (ts );
512+
513+ return 0 ;
514+ }
515+
516+ #ifdef CONFIG_USERSPACE
517+ #include <zephyr/internal/syscall_handler.h>
518+ static inline int z_vrfy_zephyr_ll_task_sem_alloc (struct task * task )
519+ {
520+ if (!task )
521+ return - EINVAL ;
522+ K_OOPS (K_SYSCALL_MEMORY_WRITE (task , sizeof (* task )));
523+ if (!task -> priv_data )
524+ return - EINVAL ;
525+ K_OOPS (K_SYSCALL_MEMORY_WRITE (task -> priv_data , sizeof (struct zephyr_ll_pdata )));
526+
527+ return z_impl_zephyr_ll_task_sem_alloc (task );
528+ }
529+ #include <zephyr/syscalls/zephyr_ll_task_sem_alloc_mrsh.c>
530+
531+ static inline int z_vrfy_zephyr_ll_task_sem_free (struct task * task )
532+ {
533+ if (!task )
534+ return - EINVAL ;
535+ K_OOPS (K_SYSCALL_MEMORY_WRITE (task , sizeof (* task )));
536+ if (!task -> priv_data )
537+ return - EINVAL ;
538+ K_OOPS (K_SYSCALL_MEMORY_WRITE (task -> priv_data , sizeof (struct zephyr_ll_pdata )));
539+
540+ return z_impl_zephyr_ll_task_sem_free (task );
541+ }
542+ #include <zephyr/syscalls/zephyr_ll_task_sem_free_mrsh.c>
543+ #endif
544+ #endif
545+
451546/*
452547 * This is synchronous - after this returns the object can be destroyed!
453548 * Assertion: under Zephyr this is always called from a thread context!
@@ -505,10 +600,13 @@ static int zephyr_ll_task_free(void *data, struct task *task)
505600
506601 if (must_wait )
507602 /* Wait for up to 100 periods */
508- k_sem_take (& pdata -> sem , K_USEC (LL_TIMER_PERIOD_US * 100 ));
603+ k_sem_take (pdata -> sem_p , K_USEC (LL_TIMER_PERIOD_US * 100 ));
509604
510605 /* Protect against racing with schedule_task() */
511606 zephyr_ll_lock (sch , & flags );
607+ #if CONFIG_DYNAMIC_OBJECTS
608+ zephyr_ll_task_sem_free (task );
609+ #endif
512610 task -> priv_data = NULL ;
513611 sof_heap_free (sch -> heap , pdata );
514612 zephyr_ll_unlock (sch , & flags );
@@ -573,6 +671,7 @@ static void zephyr_ll_scheduler_free(void *data, uint32_t flags)
573671struct k_thread * zephyr_ll_init_context (void * data , struct task * task )
574672{
575673 struct zephyr_ll * sch = data ;
674+ struct zephyr_ll_pdata * pdata = task -> priv_data ;
576675 int ret ;
577676
578677 /*
@@ -587,7 +686,7 @@ struct k_thread *zephyr_ll_init_context(void *data, struct task *task)
587686 }
588687
589688 assert (!k_is_user_context ());
590- k_thread_access_grant (zephyr_domain_thread_tid (sch -> ll_domain ), sch -> lock );
689+ k_thread_access_grant (zephyr_domain_thread_tid (sch -> ll_domain ), sch -> lock , pdata -> sem_p );
591690
592691 tr_dbg (& ll_tr , "granting access to lock %p for thread %p" , sch -> lock ,
593692 zephyr_domain_thread_tid (sch -> ll_domain ));
@@ -698,10 +797,21 @@ int zephyr_ll_task_init(struct task *task,
698797
699798 memset (pdata , 0 , sizeof (* pdata ));
700799
701- k_sem_init (& pdata -> sem , 0 , 1 );
702-
703800 task -> priv_data = pdata ;
704801
802+ #if CONFIG_DYNAMIC_OBJECTS
803+ ret = zephyr_ll_task_sem_alloc (task );
804+ if (ret < 0 ) {
805+ sof_heap_free (heap , pdata );
806+ task -> priv_data = NULL ;
807+ return ret ;
808+ }
809+ #else
810+ pdata -> sem_p = & pdata -> sem ;
811+ #endif
812+
813+ k_sem_init (pdata -> sem_p , 0 , 1 );
814+
705815 return 0 ;
706816}
707817EXPORT_SYMBOL (zephyr_ll_task_init );
0 commit comments