Skip to content

Commit 633fc9f

Browse files
committed
ipc: allocate userspace IPC thread dynamically
Prepare for multi-core support: allocate the IPC thread dynamically and extract thread initialisation into a separate function. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
1 parent 18623a4 commit 633fc9f

1 file changed

Lines changed: 55 additions & 24 deletions

File tree

src/ipc/ipc-common.c

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,6 @@ void ipc_schedule_process(struct ipc *ipc)
394394
#define IPC_USER_EVENT_CMD BIT(0)
395395
#define IPC_USER_EVENT_STOP BIT(1)
396396

397-
static struct k_thread ipc_user_thread;
398397
static K_THREAD_STACK_DEFINE(ipc_user_stack, CONFIG_SOF_IPC_USER_THREAD_STACK_SIZE);
399398

400399
/**
@@ -617,6 +616,55 @@ static void ipc_user_thread_fn(void *p1, void *p2, void *p3)
617616
}
618617
}
619618

619+
__cold static int ipc_user_init_thread(struct ipc_user *ipc_user)
620+
{
621+
char thread_name[] = "ll_user0";
622+
int ret;
623+
624+
assert_can_be_cold();
625+
626+
/* Allocate kernel objects for the user-space thread */
627+
ipc_user->event = k_object_alloc(K_OBJ_EVENT);
628+
if (!ipc_user->event) {
629+
LOG_ERR("user IPC event alloc failed");
630+
return -ENOMEM;
631+
}
632+
k_event_init(ipc_user->event);
633+
634+
ipc_user->thread = k_object_alloc(K_OBJ_THREAD);
635+
if (!ipc_user->thread) {
636+
LOG_ERR("user IPC thread alloc failed");
637+
ret = -ENOMEM;
638+
goto e_event;
639+
}
640+
641+
k_thread_create(ipc_user->thread, ipc_user_stack,
642+
CONFIG_SOF_IPC_USER_THREAD_STACK_SIZE,
643+
ipc_user_thread_fn, ipc_user, NULL, NULL,
644+
-1, K_USER, K_FOREVER);
645+
646+
k_thread_cpu_pin(ipc_user->thread, PLATFORM_PRIMARY_CORE_ID);
647+
k_thread_name_set(ipc_user->thread, thread_name);
648+
649+
/*
650+
* Each userspace IPC thread must be able to wait on its private event
651+
* and signal completion on the primary core semaphore
652+
*/
653+
k_thread_access_grant(ipc_user->thread, ipc_user->sem, ipc_user->event);
654+
user_grant_dai_access_all(ipc_user->thread);
655+
user_grant_dma_access_all(ipc_user->thread);
656+
pipeline_posn_grant_access(ipc_user->thread);
657+
k_mem_domain_add_thread(zephyr_ll_mem_domain(), ipc_user->thread);
658+
user_ll_grant_access(ipc_user->thread);
659+
660+
return 0;
661+
662+
e_event:
663+
k_object_free(ipc_user->event);
664+
665+
return ret;
666+
}
667+
620668
__cold int ipc_user_init(void)
621669
{
622670
struct ipc *ipc = ipc_get();
@@ -671,35 +719,18 @@ __cold int ipc_user_init(void)
671719

672720
k_sem_init(ipc_user->sem, 0, 1);
673721

674-
/* Allocate kernel objects for the user-space thread */
675-
ipc_user->event = k_object_alloc(K_OBJ_EVENT);
676-
if (!ipc_user->event) {
677-
LOG_ERR("user IPC event alloc failed");
722+
ret = ipc_user_init_thread(ipc_user);
723+
if (ret < 0) {
724+
LOG_ERR("user IPC thread initialization failed");
678725
k_panic();
679726
}
680-
k_event_init(ipc_user->event);
681-
682-
k_thread_create(&ipc_user_thread, ipc_user_stack,
683-
CONFIG_SOF_IPC_USER_THREAD_STACK_SIZE,
684-
ipc_user_thread_fn, ipc_user, NULL, NULL,
685-
-1, K_USER, K_FOREVER);
686-
687-
ipc_user->thread = &ipc_user_thread;
688-
k_thread_access_grant(&ipc_user_thread, ipc_user->sem, ipc_user->event);
689-
user_grant_dai_access_all(&ipc_user_thread);
690-
user_grant_dma_access_all(&ipc_user_thread);
691-
user_access_to_mailbox(zephyr_ll_mem_domain(), &ipc_user_thread);
692-
user_ll_grant_access(&ipc_user_thread);
693-
pipeline_posn_grant_access(&ipc_user_thread);
694-
k_mem_domain_add_thread(zephyr_ll_mem_domain(), &ipc_user_thread);
695727

696-
k_thread_cpu_pin(&ipc_user_thread, PLATFORM_PRIMARY_CORE_ID);
697-
k_thread_name_set(&ipc_user_thread, "ipc_user");
728+
user_access_to_mailbox(zephyr_ll_mem_domain(), ipc_user->thread);
698729

699730
/* Store references in ipc struct so kernel handler can forward commands */
700731
ipc->ipc_user_pdata = ipc_user;
701732

702-
k_thread_start(&ipc_user_thread);
733+
k_thread_start(ipc_user->thread);
703734

704735
struct task *task = zephyr_ll_task_alloc();
705736
schedule_task_init_ll(task, SOF_UUID(ipc_uuid), SOF_SCHEDULE_LL_TIMER,
@@ -710,7 +741,7 @@ __cold int ipc_user_init(void)
710741
* Needed so user-space dai_common_new() can call
711742
* k_thread_access_grant(audio_thread, dai_mutex) from user context.
712743
*/
713-
k_thread_access_grant(&ipc_user_thread, ipc_user->audio_thread);
744+
k_thread_access_grant(ipc_user->thread, ipc_user->audio_thread);
714745

715746
/* Wait for user thread startup — consumes the initial k_sem_give from thread */
716747
k_sem_take(ipc->ipc_user_pdata->sem, K_FOREVER);

0 commit comments

Comments
 (0)