@@ -41,7 +41,7 @@ struct zephyr_ll {
4141struct zephyr_ll_pdata {
4242 bool run ;
4343 bool freeing ;
44- struct k_sem sem ;
44+ struct k_sem * sem ;
4545};
4646
4747#if CONFIG_SOF_USERSPACE_LL
@@ -136,7 +136,7 @@ static void zephyr_ll_task_done(struct zephyr_ll *sch,
136136 * zephyr_ll_task_free() is trying to free this task. Complete
137137 * it and signal the semaphore to let the function proceed
138138 */
139- k_sem_give (& pdata -> sem );
139+ k_sem_give (pdata -> sem );
140140
141141 tr_info (& ll_tr , "task complete %p %pU" , task , task -> uid );
142142 tr_info (& ll_tr , "num_tasks %d total_num_tasks %ld" ,
@@ -448,6 +448,94 @@ static int zephyr_ll_task_schedule_after(void *data, struct task *task, uint64_t
448448 return zephyr_ll_task_schedule_common (sch , task , start , period , after , false);
449449}
450450
451+ struct list_item zephyr_ll_task_sem_list = LIST_INIT (zephyr_ll_task_sem_list );
452+
453+ struct zephyr_ll_task_sem {
454+ struct task * task ;
455+ struct k_sem * sem ;
456+ struct list_item list ;
457+ };
458+
459+ int z_impl_zephyr_ll_task_sem_alloc (struct task * task )
460+ {
461+ struct zephyr_ll_pdata * pdata = task -> priv_data ;
462+ struct zephyr_ll_task_sem * ts = rmalloc (SOF_MEM_FLAG_COHERENT , sizeof (* ts ));
463+
464+ if (!ts )
465+ return - ENOMEM ;
466+
467+ ts -> sem = k_object_alloc (K_OBJ_SEM );
468+ if (!ts -> sem ) {
469+ rfree (ts );
470+ return - ENOMEM ;
471+ }
472+
473+ k_sem_init (ts -> sem , 0 , 1 );
474+
475+ ts -> task = task ;
476+ pdata -> sem = ts -> sem ;
477+ list_item_append (& ts -> list , & zephyr_ll_task_sem_list );
478+
479+ return 0 ;
480+ }
481+
482+ int z_impl_zephyr_ll_task_sem_free (struct task * task )
483+ {
484+ struct zephyr_ll_pdata * pdata = task -> priv_data ;
485+ struct list_item * list ;
486+ struct zephyr_ll_task_sem * ts ;
487+ bool found = false;
488+
489+ list_for_item (list , & zephyr_ll_task_sem_list ) {
490+ ts = container_of (list , struct zephyr_ll_task_sem , list );
491+ if (ts -> task == task ) {
492+ found = true;
493+ break ;
494+ }
495+ }
496+
497+ if (!found )
498+ return - ENOENT ;
499+
500+ if (pdata -> sem != ts -> sem )
501+ return - EINVAL ;
502+
503+ list_item_del (list );
504+ k_object_free (ts -> sem );
505+ rfree (ts );
506+
507+ return 0 ;
508+ }
509+
510+ #ifdef CONFIG_USERSPACE
511+ #include <zephyr/internal/syscall_handler.h>
512+ static inline int z_vrfy_zephyr_ll_task_sem_alloc (struct task * task )
513+ {
514+ if (!task )
515+ return - EINVAL ;
516+ K_OOPS (K_SYSCALL_MEMORY_WRITE (task , sizeof (* task )));
517+ if (!task -> priv_data )
518+ return - EINVAL ;
519+ K_OOPS (K_SYSCALL_MEMORY_WRITE (task -> priv_data , sizeof (struct zephyr_ll_pdata )));
520+
521+ return z_impl_zephyr_ll_task_sem_alloc (task );
522+ }
523+ #include <zephyr/syscalls/zephyr_ll_task_sem_alloc_mrsh.c>
524+
525+ static inline int z_vrfy_zephyr_ll_task_sem_free (struct task * task )
526+ {
527+ if (!task )
528+ return - EINVAL ;
529+ K_OOPS (K_SYSCALL_MEMORY_WRITE (task , sizeof (* task )));
530+ if (!task -> priv_data )
531+ return - EINVAL ;
532+ K_OOPS (K_SYSCALL_MEMORY_WRITE (task -> priv_data , sizeof (struct zephyr_ll_pdata )));
533+
534+ return z_impl_zephyr_ll_task_sem_free (task );
535+ }
536+ #include <zephyr/syscalls/zephyr_ll_task_sem_free_mrsh.c>
537+ #endif
538+
451539/*
452540 * This is synchronous - after this returns the object can be destroyed!
453541 * Assertion: under Zephyr this is always called from a thread context!
@@ -505,10 +593,11 @@ static int zephyr_ll_task_free(void *data, struct task *task)
505593
506594 if (must_wait )
507595 /* Wait for up to 100 periods */
508- k_sem_take (& pdata -> sem , K_USEC (LL_TIMER_PERIOD_US * 100 ));
596+ k_sem_take (pdata -> sem , K_USEC (LL_TIMER_PERIOD_US * 100 ));
509597
510598 /* Protect against racing with schedule_task() */
511599 zephyr_ll_lock (sch , & flags );
600+ zephyr_ll_task_sem_free (task );
512601 task -> priv_data = NULL ;
513602 sof_heap_free (sch -> heap , pdata );
514603 zephyr_ll_unlock (sch , & flags );
@@ -573,6 +662,7 @@ static void zephyr_ll_scheduler_free(void *data, uint32_t flags)
573662struct k_thread * zephyr_ll_init_context (void * data , struct task * task )
574663{
575664 struct zephyr_ll * sch = data ;
665+ struct zephyr_ll_pdata * pdata = task -> priv_data ;
576666 int ret ;
577667
578668 /*
@@ -587,7 +677,7 @@ struct k_thread *zephyr_ll_init_context(void *data, struct task *task)
587677 }
588678
589679 assert (!k_is_user_context ());
590- k_thread_access_grant (zephyr_domain_thread_tid (sch -> ll_domain ), sch -> lock );
680+ k_thread_access_grant (zephyr_domain_thread_tid (sch -> ll_domain ), sch -> lock , pdata -> sem );
591681
592682 tr_dbg (& ll_tr , "granting access to lock %p for thread %p" , sch -> lock ,
593683 zephyr_domain_thread_tid (sch -> ll_domain ));
@@ -698,10 +788,15 @@ int zephyr_ll_task_init(struct task *task,
698788
699789 memset (pdata , 0 , sizeof (* pdata ));
700790
701- k_sem_init (& pdata -> sem , 0 , 1 );
702-
703791 task -> priv_data = pdata ;
704792
793+ ret = zephyr_ll_task_sem_alloc (task );
794+ if (ret < 0 ) {
795+ sof_heap_free (heap , pdata );
796+ task -> priv_data = NULL ;
797+ return ret ;
798+ }
799+
705800 return 0 ;
706801}
707802EXPORT_SYMBOL (zephyr_ll_task_init );
0 commit comments