diff --git a/src/arch/xtensa/include/arch/schedule/task.h b/src/arch/xtensa/include/arch/schedule/task.h index 3405c262e2f9..156bcfa51206 100644 --- a/src/arch/xtensa/include/arch/schedule/task.h +++ b/src/arch/xtensa/include/arch/schedule/task.h @@ -41,8 +41,9 @@ void task_context_set(void *task_ctx); * \brief Initializes task context. * \param[in,out] task Task with context to be initialized. * \param[in,out] entry Entry point for task execution. + * \param[in,out] data Parameter data for entry point. */ -int task_context_init(struct task *task, void *entry); +int task_context_init(struct task *task, void *entry, void *data); /** * \brief Frees task context. diff --git a/src/arch/xtensa/init.c b/src/arch/xtensa/init.c index 4efb884a6e8f..844a85924e25 100644 --- a/src/arch/xtensa/init.c +++ b/src/arch/xtensa/init.c @@ -96,6 +96,8 @@ int arch_init(struct sof *sof) #include #include #include +#include +#include #include #include #include @@ -120,7 +122,8 @@ int slave_core_init(struct sof *sof) platform_interrupt_init(); trace_point(TRACE_BOOT_PLATFORM_SCHED); - scheduler_init(sof); + scheduler_init_edf(sof); + scheduler_init_ll(); /* initialize IDC mechanism */ trace_point(TRACE_BOOT_PLATFORM_IDC); diff --git a/src/arch/xtensa/schedule/schedule.c b/src/arch/xtensa/schedule/schedule.c index 1056debaf540..23382fdf3784 100644 --- a/src/arch/xtensa/schedule/schedule.c +++ b/src/arch/xtensa/schedule/schedule.c @@ -14,9 +14,9 @@ #include #include -struct schedule_data **arch_schedule_get_data(void) +struct schedulers **arch_schedulers_get(void) { struct core_context *ctx = (struct core_context *)cpu_read_threadptr(); - return &ctx->sch_data; + return &ctx->schedulers; } diff --git a/src/arch/xtensa/schedule/task.c b/src/arch/xtensa/schedule/task.c index e27ee8f0bee7..f56af97d44c0 100644 --- a/src/arch/xtensa/schedule/task.c +++ b/src/arch/xtensa/schedule/task.c @@ -62,7 +62,7 @@ void task_context_set(void *task_ctx) ctx->td.xtos_active_task = task_ctx; } -int task_context_init(struct task *task, void *entry) +int task_context_init(struct task *task, void *entry, void *data) { struct edf_task_pdata *edf_pdata = edf_sch_get_pdata(task); xtos_task_context *ctx; @@ -97,8 +97,9 @@ int task_context_init(struct task *task, void *entry) */ sp->ps = PS_WOECALL4_ABI | PS_UM; - /* a6 is first parameter */ + /* a6 and a7 are the first parameters */ sp->a6 = (uint32_t)task; + sp->a7 = (uint32_t)data; ctx->stack_pointer = sp; diff --git a/src/arch/xtensa/xtos/xtos-structs.h b/src/arch/xtensa/xtos/xtos-structs.h index af816e146c37..bee5f76f632d 100644 --- a/src/arch/xtensa/xtos/xtos-structs.h +++ b/src/arch/xtensa/xtos/xtos-structs.h @@ -16,7 +16,7 @@ struct idc; struct notify; -struct schedule_data; +struct schedulers; struct task; struct thread_data { @@ -40,7 +40,7 @@ struct xtos_core_data { struct core_context { struct thread_data td; struct task *main_task; - struct schedule_data *sch_data; + struct schedulers *schedulers; struct notify *notify; struct idc *idc; }; diff --git a/src/audio/pipeline.c b/src/audio/pipeline.c index e970a60ede01..ad556f7ec5e2 100644 --- a/src/audio/pipeline.c +++ b/src/audio/pipeline.c @@ -958,14 +958,7 @@ void pipeline_schedule_copy(struct pipeline *p, uint64_t start) void pipeline_schedule_cancel(struct pipeline *p) { - int err; - - /* cancel and wait for pipeline to complete */ - err = schedule_task_cancel(&p->pipe_task); - if (err < 0) - trace_pipe_error_with_ids(p, "pipeline_schedule_cancel() " - "error: schedule_task_cancel() " - "failed, err = %d", err); + schedule_task_cancel(&p->pipe_task); } static enum task_state pipeline_task(void *arg) diff --git a/src/include/sof/schedule/edf_schedule.h b/src/include/sof/schedule/edf_schedule.h index 3d4d3d8efa80..625ab0eae4d8 100644 --- a/src/include/sof/schedule/edf_schedule.h +++ b/src/include/sof/schedule/edf_schedule.h @@ -13,6 +13,8 @@ #include #include +struct sof; + /* schedule tracing */ #define trace_edf_sch(format, ...) \ trace_event(TRACE_CLASS_EDF, format, ##__VA_ARGS__) @@ -33,4 +35,6 @@ struct edf_task_pdata { void *ctx; }; +int scheduler_init_edf(struct sof *sof); + #endif /* __SOF_SCHEDULE_EDF_SCHEDULE_H__ */ diff --git a/src/include/sof/schedule/ll_schedule.h b/src/include/sof/schedule/ll_schedule.h index 647fd0149978..d36dabec3756 100644 --- a/src/include/sof/schedule/ll_schedule.h +++ b/src/include/sof/schedule/ll_schedule.h @@ -37,4 +37,6 @@ struct ll_task_pdata { uint64_t period; }; +int scheduler_init_ll(void); + #endif /* __SOF_SCHEDULE_LL_SCHEDULE_H__ */ diff --git a/src/include/sof/schedule/schedule.h b/src/include/sof/schedule/schedule.h index 6d1bf5109e4e..d3da65dc205a 100644 --- a/src/include/sof/schedule/schedule.h +++ b/src/include/sof/schedule/schedule.h @@ -9,16 +9,13 @@ #ifndef __SOF_SCHEDULE_SCHEDULE_H__ #define __SOF_SCHEDULE_SCHEDULE_H__ +#include #include #include #include #include #include -struct edf_schedule_data; -struct ll_schedule_data; -struct sof; - /* schedule tracing */ #define trace_schedule(format, ...) \ trace_event(TRACE_CLASS_EDF, format, ##__VA_ARGS__) @@ -43,75 +40,140 @@ enum { #define SOF_SCHEDULE_FLAG_IDLE (2 << 0) struct scheduler_ops { - void (*schedule_task)(struct task *w, uint64_t start, + void (*schedule_task)(void *data, struct task *task, uint64_t start, uint64_t period); - int (*schedule_task_init)(struct task *task); - void (*schedule_task_running)(struct task *task); - void (*schedule_task_complete)(struct task *task); - void (*reschedule_task)(struct task *task, uint64_t start); - int (*schedule_task_cancel)(struct task *task); - void (*schedule_task_free)(struct task *task); - int (*scheduler_init)(struct sof *sof); - void (*scheduler_free)(void); - void (*scheduler_run)(void); + int (*schedule_task_init)(void *data, struct task *task); + void (*schedule_task_running)(void *data, struct task *task); + void (*schedule_task_complete)(void *data, struct task *task); + void (*reschedule_task)(void *data, struct task *task, uint64_t start); + void (*schedule_task_cancel)(void *data, struct task *task); + void (*schedule_task_free)(void *data, struct task *task); + void (*scheduler_free)(void *data); + void (*scheduler_run)(void *data); }; struct schedule_data { - struct ll_schedule_data *ll_sch_data; - struct edf_schedule_data *edf_sch_data; + struct list_item list; + int type; + const struct scheduler_ops *ops; + void *data; +}; + +struct schedulers { + struct list_item list; }; -extern struct scheduler_ops schedule_edf_ops; -extern struct scheduler_ops schedule_ll_ops; +struct schedulers **arch_schedulers_get(void); static inline void schedule_task_running(struct task *task) { - if (task->ops->schedule_task_running) - task->ops->schedule_task_running(task); + struct schedulers *schedulers = *arch_schedulers_get(); + struct schedule_data *sch; + struct list_item *slist; + + list_for_item(slist, &schedulers->list) { + sch = container_of(slist, struct schedule_data, list); + if (task->type == sch->type && sch->ops->schedule_task_running) + sch->ops->schedule_task_running(sch->data, task); + } } static inline void schedule_task_complete(struct task *task) { - if (task->ops->schedule_task_complete) - task->ops->schedule_task_complete(task); + struct schedulers *schedulers = *arch_schedulers_get(); + struct schedule_data *sch; + struct list_item *slist; + + list_for_item(slist, &schedulers->list) { + sch = container_of(slist, struct schedule_data, list); + if (task->type == sch->type && sch->ops->schedule_task_complete) + sch->ops->schedule_task_complete(sch->data, task); + } } static inline void schedule_task(struct task *task, uint64_t start, uint64_t period) { - if (task->ops->schedule_task) - task->ops->schedule_task(task, start, period); + struct schedulers *schedulers = *arch_schedulers_get(); + struct schedule_data *sch; + struct list_item *slist; + + list_for_item(slist, &schedulers->list) { + sch = container_of(slist, struct schedule_data, list); + if (task->type == sch->type && sch->ops->schedule_task) + sch->ops->schedule_task(sch->data, task, start, period); + } } static inline void reschedule_task(struct task *task, uint64_t start) { - if (task->ops->reschedule_task) - task->ops->reschedule_task(task, start); + struct schedulers *schedulers = *arch_schedulers_get(); + struct schedule_data *sch; + struct list_item *slist; + + list_for_item(slist, &schedulers->list) { + sch = container_of(slist, struct schedule_data, list); + if (task->type == sch->type && sch->ops->reschedule_task) + sch->ops->reschedule_task(sch->data, task, start); + } } -static inline int schedule_task_cancel(struct task *task) +static inline void schedule_task_cancel(struct task *task) { - if (task->ops->schedule_task_cancel) - return task->ops->schedule_task_cancel(task); - return 0; + struct schedulers *schedulers = *arch_schedulers_get(); + struct schedule_data *sch; + struct list_item *slist; + + list_for_item(slist, &schedulers->list) { + sch = container_of(slist, struct schedule_data, list); + if (task->type == sch->type && sch->ops->schedule_task_cancel) + sch->ops->schedule_task_cancel(sch->data, task); + } } static inline void schedule_task_free(struct task *task) { - if (task->ops->schedule_task_free) - task->ops->schedule_task_free(task); + struct schedulers *schedulers = *arch_schedulers_get(); + struct schedule_data *sch; + struct list_item *slist; + + list_for_item(slist, &schedulers->list) { + sch = container_of(slist, struct schedule_data, list); + if (task->type == sch->type && sch->ops->schedule_task_free) + sch->ops->schedule_task_free(sch->data, task); + } +} + +static inline void schedule_free(void) +{ + struct schedulers *schedulers = *arch_schedulers_get(); + struct schedule_data *sch; + struct list_item *slist; + + list_for_item(slist, &schedulers->list) { + sch = container_of(slist, struct schedule_data, list); + if (sch->ops->scheduler_free) + sch->ops->scheduler_free(sch->data); + } } -struct schedule_data **arch_schedule_get_data(void); +static inline void schedule(void) +{ + struct schedulers *schedulers = *arch_schedulers_get(); + struct schedule_data *sch; + struct list_item *slist; + + list_for_item(slist, &schedulers->list) { + sch = container_of(slist, struct schedule_data, list); + if (sch->ops->scheduler_run) + sch->ops->scheduler_run(sch->data); + } +} int schedule_task_init(struct task *task, uint16_t type, uint16_t priority, enum task_state (*func)(void *data), void *data, uint16_t core, uint32_t flags); -void schedule_free(void); - -void schedule(void); - -int scheduler_init(struct sof *sof); +void scheduler_init(int type, const struct scheduler_ops *ops, void *data); #endif /* __SOF_SCHEDULE_SCHEDULE_H__ */ diff --git a/src/include/sof/schedule/task.h b/src/include/sof/schedule/task.h index 72daff0ab52c..fc6cac132b32 100644 --- a/src/include/sof/schedule/task.h +++ b/src/include/sof/schedule/task.h @@ -12,7 +12,6 @@ #include #include -struct scheduler_ops; struct sof; #define SOF_TASK_PRI_HIGH 0 /* priority level 0 - high */ @@ -50,7 +49,6 @@ struct task { void *data; enum task_state (*func)(void *data); struct list_item list; - const struct scheduler_ops *ops; void *private; }; diff --git a/src/platform/baytrail/platform.c b/src/platform/baytrail/platform.c index 697c072c7550..e636496b4027 100644 --- a/src/platform/baytrail/platform.c +++ b/src/platform/baytrail/platform.c @@ -20,7 +20,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -193,7 +194,8 @@ int platform_init(struct sof *sof) clock_init(); trace_point(TRACE_BOOT_PLATFORM_SCHED); - scheduler_init(sof); + scheduler_init_edf(sof); + scheduler_init_ll(); /* init the system agent */ trace_point(TRACE_BOOT_PLATFORM_AGENT); diff --git a/src/platform/haswell/platform.c b/src/platform/haswell/platform.c index 3d6fd1c8e073..be3eede912e3 100644 --- a/src/platform/haswell/platform.c +++ b/src/platform/haswell/platform.c @@ -18,7 +18,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -182,7 +183,8 @@ int platform_init(struct sof *sof) clock_init(); trace_point(TRACE_BOOT_PLATFORM_SCHED); - scheduler_init(sof); + scheduler_init_edf(sof); + scheduler_init_ll(); /* init the system agent */ trace_point(TRACE_BOOT_PLATFORM_AGENT); diff --git a/src/platform/imx8/platform.c b/src/platform/imx8/platform.c index b6c49915b0c2..2d136126e62e 100644 --- a/src/platform/imx8/platform.c +++ b/src/platform/imx8/platform.c @@ -16,7 +16,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -149,7 +150,8 @@ int platform_init(struct sof *sof) struct dai *esai; clock_init(); - scheduler_init(sof); + scheduler_init_edf(sof); + scheduler_init_ll(); platform_timer_start(platform_timer); sa_init(sof); diff --git a/src/platform/intel/cavs/platform.c b/src/platform/intel/cavs/platform.c index 1b9ea421382d..28d168dcca63 100644 --- a/src/platform/intel/cavs/platform.c +++ b/src/platform/intel/cavs/platform.c @@ -25,7 +25,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -416,7 +417,8 @@ int platform_init(struct sof *sof) clock_init(); trace_point(TRACE_BOOT_PLATFORM_SCHED); - scheduler_init(sof); + scheduler_init_edf(sof); + scheduler_init_ll(); /* init the system agent */ trace_point(TRACE_BOOT_PLATFORM_AGENT); diff --git a/src/schedule/edf_schedule.c b/src/schedule/edf_schedule.c index 06218207be32..bcb1feb97281 100644 --- a/src/schedule/edf_schedule.c +++ b/src/schedule/edf_schedule.c @@ -28,24 +28,29 @@ struct edf_schedule_data { int irq; }; -static void schedule_edf_task_run(struct task *task) +struct scheduler_ops schedule_edf_ops; + +static void schedule_edf_task_complete(void *data, struct task *task); +static void schedule_edf_task_running(void *data, struct task *task); +static void schedule_edf(void *data); + +static void schedule_edf_task_run(struct task *task, void *data) { while (1) { /* execute task function and remove task from the list * only if completed */ if (task->func(task->data) == SOF_TASK_STATE_COMPLETED) - task->ops->schedule_task_complete(task); + schedule_edf_task_complete(data, task); /* find new task for execution */ - task->ops->scheduler_run(); + schedule_edf(data); } } -static void edf_scheduler_run(void *unused) +static void edf_scheduler_run(void *data) { - struct edf_schedule_data *edf_sch = - (*arch_schedule_get_data())->edf_sch_data; + struct edf_schedule_data *edf_sch = data; uint64_t current = platform_timer_get(platform_timer); int priority_next = SOF_TASK_PRI_IDLE; uint64_t delta_next = UINT64_MAX; @@ -102,14 +107,13 @@ static void edf_scheduler_run(void *unused) /* having next task is mandatory */ assert(task_next); - task_next->ops->schedule_task_running(task_next); + schedule_edf_task_running(data, task_next); } -static void schedule_edf_task(struct task *task, uint64_t start, +static void schedule_edf_task(void *data, struct task *task, uint64_t start, uint64_t period) { - struct edf_schedule_data *edf_sch = - (*arch_schedule_get_data())->edf_sch_data; + struct edf_schedule_data *edf_sch = data; struct edf_task_pdata *edf_pdata = edf_sch_get_pdata(task); uint32_t flags; uint64_t current; @@ -146,10 +150,10 @@ static void schedule_edf_task(struct task *task, uint64_t start, irq_local_enable(flags); - task->ops->scheduler_run(); + schedule_edf(data); } -static int schedule_edf_task_init(struct task *task) +static int schedule_edf_task_init(void *data, struct task *task) { struct edf_task_pdata *edf_pdata; @@ -166,7 +170,7 @@ static int schedule_edf_task_init(struct task *task) edf_sch_set_pdata(task, edf_pdata); - if (task_context_init(task, &schedule_edf_task_run) < 0) { + if (task_context_init(task, &schedule_edf_task_run, data) < 0) { trace_edf_sch_error("schedule_edf_task_init() error: init " "context failed"); rfree(edf_pdata); @@ -182,7 +186,7 @@ static int schedule_edf_task_init(struct task *task) return 0; } -static void schedule_edf_task_running(struct task *task) +static void schedule_edf_task_running(void *data, struct task *task) { struct edf_task_pdata *edf_pdata = edf_sch_get_pdata(task); uint32_t flags; @@ -197,7 +201,7 @@ static void schedule_edf_task_running(struct task *task) irq_local_enable(flags); } -static void schedule_edf_task_complete(struct task *task) +static void schedule_edf_task_complete(void *data, struct task *task) { uint32_t flags; @@ -211,7 +215,7 @@ static void schedule_edf_task_complete(struct task *task) irq_local_enable(flags); } -static int schedule_edf_task_cancel(struct task *task) +static void schedule_edf_task_cancel(void *data, struct task *task) { uint32_t flags; @@ -226,11 +230,9 @@ static int schedule_edf_task_cancel(struct task *task) } irq_local_enable(flags); - - return 0; } -static void schedule_edf_task_free(struct task *task) +static void schedule_edf_task_free(void *data, struct task *task) { struct edf_task_pdata *edf_pdata = edf_sch_get_pdata(task); uint32_t flags; @@ -246,21 +248,18 @@ static void schedule_edf_task_free(struct task *task) irq_local_enable(flags); } -static int edf_scheduler_init(struct sof *sof) +int scheduler_init_edf(struct sof *sof) { - struct schedule_data *sch = *arch_schedule_get_data(); struct edf_schedule_data *edf_sch; trace_edf_sch("edf_scheduler_init()"); - sch->edf_sch_data = rzalloc(RZONE_SYS, SOF_MEM_CAPS_RAM, - sizeof(*sch->edf_sch_data)); - - /* initialize EDF schedule data */ - edf_sch = sch->edf_sch_data; + edf_sch = rzalloc(RZONE_SYS, SOF_MEM_CAPS_RAM, sizeof(*edf_sch)); list_init(&edf_sch->list); edf_sch->clock = PLATFORM_SCHED_CLOCK; + scheduler_init(SOF_SCHEDULE_EDF, &schedule_edf_ops, edf_sch); + /* initialize main task context before enabling interrupt */ task_main_init(sof); @@ -277,10 +276,9 @@ static int edf_scheduler_init(struct sof *sof) return 0; } -static void edf_scheduler_free(void) +static void scheduler_free_edf(void *data) { - struct edf_schedule_data *edf_sch = - (*arch_schedule_get_data())->edf_sch_data; + struct edf_schedule_data *edf_sch = data; uint32_t flags; irq_local_disable(flags); @@ -297,10 +295,9 @@ static void edf_scheduler_free(void) irq_local_enable(flags); } -static void schedule_edf(void) +static void schedule_edf(void *data) { - struct edf_schedule_data *edf_sch = - (*arch_schedule_get_data())->edf_sch_data; + struct edf_schedule_data *edf_sch = data; interrupt_set(edf_sch->irq); } @@ -313,7 +310,6 @@ struct scheduler_ops schedule_edf_ops = { .reschedule_task = NULL, .schedule_task_cancel = schedule_edf_task_cancel, .schedule_task_free = schedule_edf_task_free, - .scheduler_init = edf_scheduler_init, - .scheduler_free = edf_scheduler_free, + .scheduler_free = scheduler_free_edf, .scheduler_run = schedule_edf }; diff --git a/src/schedule/ll_schedule.c b/src/schedule/ll_schedule.c index 6895188ad890..f8faa6348d58 100644 --- a/src/schedule/ll_schedule.c +++ b/src/schedule/ll_schedule.c @@ -64,6 +64,8 @@ struct ll_queue_shared_context { static struct ll_queue_shared_context *ll_shared_ctx; +struct scheduler_ops schedule_ll_ops; + /* calculate next timeout */ static uint64_t queue_calc_next_timeout(struct ll_schedule_data *queue, uint64_t start) @@ -351,10 +353,10 @@ static void insert_task_to_queue(struct task *w, struct list_item *q_list) list_item_append(&w->list, q_list); } -static void schedule_ll_task(struct task *w, uint64_t start, uint64_t period) +static void schedule_ll_task(void *data, struct task *task, uint64_t start, + uint64_t period) { - struct ll_schedule_data *queue = - (*arch_schedule_get_data())->ll_sch_data; + struct ll_schedule_data *sch = data; struct ll_task_pdata *ll_pdata; struct task *ll_task; struct list_item *wlist; @@ -363,120 +365,115 @@ static void schedule_ll_task(struct task *w, uint64_t start, uint64_t period) irq_local_disable(flags); /* check to see if we are already scheduled ? */ - list_for_item(wlist, &queue->tasks) { + list_for_item(wlist, &sch->tasks) { ll_task = container_of(wlist, struct task, list); /* keep original start */ - if (ll_task == w) + if (ll_task == task) goto out; } - w->start = queue->ticks_per_msec * start / 1000; + task->start = sch->ticks_per_msec * start / 1000; /* convert start micro seconds to CPU clock ticks */ - if (w->flags & SOF_SCHEDULE_FLAG_SYNC) - w->start += ll_get_timer(queue); + if (task->flags & SOF_SCHEDULE_FLAG_SYNC) + task->start += ll_get_timer(sch); else - w->start += ll_shared_ctx->last_tick; + task->start += ll_shared_ctx->last_tick; - ll_pdata = ll_sch_get_pdata(w); + ll_pdata = ll_sch_get_pdata(task); /* invalidate if slave core */ - if (cpu_is_slave(w->core)) + if (cpu_is_slave(task->core)) dcache_invalidate_region(ll_pdata, sizeof(*ll_pdata)); ll_pdata->period = period; /* insert work into list */ - insert_task_to_queue(w, &queue->tasks); + insert_task_to_queue(task, &sch->tasks); - ll_set_timer(queue); + ll_set_timer(sch); out: irq_local_enable(flags); } -static void reschedule_ll_task(struct task *w, uint64_t start) +static void reschedule_ll_task(void *data, struct task *task, uint64_t start) { - struct ll_schedule_data *queue = - (*arch_schedule_get_data())->ll_sch_data; + struct ll_schedule_data *sch = data; struct task *ll_task; struct list_item *wlist; uint32_t flags; uint64_t time; - time = queue->ticks_per_msec * start / 1000; + time = sch->ticks_per_msec * start / 1000; /* convert start micro seconds to CPU clock ticks */ - if (w->flags & SOF_SCHEDULE_FLAG_SYNC) - time += ll_get_timer(queue); + if (task->flags & SOF_SCHEDULE_FLAG_SYNC) + time += ll_get_timer(sch); else time += ll_shared_ctx->last_tick; irq_local_disable(flags); /* check to see if we are already scheduled */ - list_for_item(wlist, &queue->tasks) { + list_for_item(wlist, &sch->tasks) { ll_task = container_of(wlist, struct task, list); /* found it */ - if (ll_task == w) + if (ll_task == task) goto found; } - insert_task_to_queue(w, &queue->tasks); + insert_task_to_queue(task, &sch->tasks); - ll_set_timer(queue); + ll_set_timer(sch); found: /* re-calc timer and re-arm */ - w->start = time; + task->start = time; irq_local_enable(flags); } -static int schedule_ll_task_cancel(struct task *w) +static void schedule_ll_task_cancel(void *data, struct task *task) { - struct ll_schedule_data *queue = - (*arch_schedule_get_data())->ll_sch_data; + struct ll_schedule_data *sch = data; struct task *ll_task; struct list_item *wlist; uint32_t flags; - int ret = 0; irq_local_disable(flags); /* check to see if we are scheduled */ - list_for_item(wlist, &queue->tasks) { + list_for_item(wlist, &sch->tasks) { ll_task = container_of(wlist, struct task, list); /* found it */ - if (ll_task == w) { - ll_clear_timer(queue); + if (ll_task == task) { + ll_clear_timer(sch); break; } } /* remove work from list */ - w->state = SOF_TASK_STATE_CANCEL; - list_item_del(&w->list); + task->state = SOF_TASK_STATE_CANCEL; + list_item_del(&task->list); irq_local_enable(flags); - - return ret; } -static void schedule_ll_task_free(struct task *w) +static void schedule_ll_task_free(void *data, struct task *task) { - uint32_t flags; struct ll_task_pdata *ll_pdata; + uint32_t flags; irq_local_disable(flags); /* release the resources */ - w->state = SOF_TASK_STATE_FREE; - ll_pdata = ll_sch_get_pdata(w); + task->state = SOF_TASK_STATE_FREE; + ll_pdata = ll_sch_get_pdata(task); rfree(ll_pdata); - ll_sch_set_pdata(w, NULL); + ll_sch_set_pdata(task, NULL); irq_local_enable(flags); } @@ -507,16 +504,17 @@ static struct ll_schedule_data *work_new_queue(struct timesource_data *ts) return queue; } -static int ll_scheduler_init(struct sof *sof) +int scheduler_init_ll(void) { - int cpu; - struct schedule_data *sch_data = *arch_schedule_get_data(); + struct ll_schedule_data *sch; struct timesource_data *ts; + int cpu; cpu = cpu_get_id(); ts = &platform_generic_queue[cpu]; - sch_data->ll_sch_data = work_new_queue(ts); + sch = work_new_queue(ts); + scheduler_init(SOF_SCHEDULE_LL, &schedule_ll_ops, sch); if (cpu == PLATFORM_MASTER_CORE_ID) { unsigned int i; @@ -538,18 +536,17 @@ static int ll_scheduler_init(struct sof *sof) } /* register system timer */ - timer_register(&platform_generic_queue[cpu].timer, queue_run, - sch_data->ll_sch_data); + timer_register(&platform_generic_queue[cpu].timer, queue_run, sch); return 0; } /* initialise our work */ -static int schedule_ll_task_init(struct task *w) +static int schedule_ll_task_init(void *data, struct task *task) { struct ll_task_pdata *ll_pdata; - if (ll_sch_get_pdata(w)) + if (ll_sch_get_pdata(task)) return -EEXIST; ll_pdata = rzalloc(RZONE_SYS_RUNTIME, SOF_MEM_CAPS_RAM, @@ -561,28 +558,27 @@ static int schedule_ll_task_init(struct task *w) } /* flush for slave core */ - if (cpu_is_slave(w->core)) + if (cpu_is_slave(task->core)) dcache_writeback_invalidate_region(ll_pdata, sizeof(*ll_pdata)); - ll_sch_set_pdata(w, ll_pdata); + ll_sch_set_pdata(task, ll_pdata); return 0; } -static void ll_scheduler_free(void) +static void scheduler_free_ll(void *data) { - struct ll_schedule_data *queue = - (*arch_schedule_get_data())->ll_sch_data; + struct ll_schedule_data *sch = data; uint32_t flags; irq_local_disable(flags); - timer_unregister(&queue->ts->timer); + timer_unregister(&sch->ts->timer); - notifier_unregister(&queue->notifier); + notifier_unregister(&sch->notifier); - list_item_del(&queue->tasks); + list_item_del(&sch->tasks); irq_local_enable(flags); } @@ -595,7 +591,6 @@ struct scheduler_ops schedule_ll_ops = { .reschedule_task = reschedule_ll_task, .schedule_task_cancel = schedule_ll_task_cancel, .schedule_task_free = schedule_ll_task_free, - .scheduler_init = ll_scheduler_init, - .scheduler_free = ll_scheduler_free, + .scheduler_free = scheduler_free_ll, .scheduler_run = NULL }; diff --git a/src/schedule/schedule.c b/src/schedule/schedule.c index 5b712ccf12fc..bab7ef6427a3 100644 --- a/src/schedule/schedule.c +++ b/src/schedule/schedule.c @@ -6,9 +6,11 @@ /* Generic scheduler */ +#include #include #include #include +#include #include #include #include @@ -16,15 +18,13 @@ #include #include -static const struct scheduler_ops *schedulers[SOF_SCHEDULE_COUNT] = { - &schedule_edf_ops, /* SOF_SCHEDULE_EDF */ - &schedule_ll_ops /* SOF_SCHEDULE_LL */ -}; - int schedule_task_init(struct task *task, uint16_t type, uint16_t priority, enum task_state (*func)(void *data), void *data, uint16_t core, uint32_t flags) { + struct schedulers *schedulers = *arch_schedulers_get(); + struct schedule_data *sch; + struct list_item *slist; int ret = 0; if (type >= SOF_SCHEDULE_COUNT) { @@ -41,51 +41,39 @@ int schedule_task_init(struct task *task, uint16_t type, uint16_t priority, task->state = SOF_TASK_STATE_INIT; task->func = func; task->data = data; - task->ops = schedulers[task->type]; - if (task->ops->schedule_task_init) - ret = task->ops->schedule_task_init(task); + list_for_item(slist, &schedulers->list) { + sch = container_of(slist, struct schedule_data, list); + if (type == sch->type && sch->ops->schedule_task_init) + return sch->ops->schedule_task_init(sch->data, task); + } out: return ret; } -int scheduler_init(struct sof *sof) +static void scheduler_register(struct schedule_data *scheduler) { - struct schedule_data **sch = arch_schedule_get_data(); - int ret = 0; - int i; + struct schedulers **sch = arch_schedulers_get(); - /* init scheduler_data */ - *sch = rzalloc(RZONE_SYS, SOF_MEM_CAPS_RAM, sizeof(**sch)); - - for (i = 0; i < SOF_SCHEDULE_COUNT; i++) { - if (schedulers[i]->scheduler_init) { - ret = schedulers[i]->scheduler_init(sof); - if (ret < 0) - goto out; - } + if (!*sch) { + /* init schedulers list */ + *sch = rzalloc(RZONE_SYS, SOF_MEM_CAPS_RAM, sizeof(**sch)); + list_init(&(*sch)->list); } -out: - return ret; -} - -void schedule_free(void) -{ - int i; - for (i = 0; i < SOF_SCHEDULE_COUNT; i++) { - if (schedulers[i]->scheduler_free) - schedulers[i]->scheduler_free(); - } + list_item_append(&scheduler->list, &(*sch)->list); } -void schedule(void) +void scheduler_init(int type, const struct scheduler_ops *ops, void *data) { - int i; + struct schedule_data *sch; - for (i = 0; i < SOF_SCHEDULE_COUNT; i++) { - if (schedulers[i]->scheduler_run) - schedulers[i]->scheduler_run(); - } + sch = rzalloc(RZONE_SYS, SOF_MEM_CAPS_RAM, sizeof(*sch)); + list_init(&sch->list); + sch->type = type; + sch->ops = ops; + sch->data = data; + + scheduler_register(sch); } diff --git a/test/cmocka/src/audio/kpb/kpb_mock.c b/test/cmocka/src/audio/kpb/kpb_mock.c index 331939b332f7..267a44ecf1a8 100644 --- a/test/cmocka/src/audio/kpb/kpb_mock.c +++ b/test/cmocka/src/audio/kpb/kpb_mock.c @@ -95,3 +95,8 @@ uint64_t clock_ms_to_ticks(int clock, uint64_t ms) return 0; } + +struct schedulers **arch_schedulers_get(void) +{ + return NULL; +} diff --git a/test/cmocka/src/audio/pipeline/pipeline_connection_mocks.c b/test/cmocka/src/audio/pipeline/pipeline_connection_mocks.c index 985bf1065400..c1aaf4743a68 100644 --- a/test/cmocka/src/audio/pipeline/pipeline_connection_mocks.c +++ b/test/cmocka/src/audio/pipeline/pipeline_connection_mocks.c @@ -6,6 +6,8 @@ #include "pipeline_connection_mocks.h" +extern struct schedulers *schedulers; + struct scheduler_ops schedule_mock_ops = { .schedule_task_free = &schedule_task_mock_free, }; @@ -35,7 +37,17 @@ struct pipeline_connect_data *get_standard_connect_objects(void) pipe->ipc_pipe = pipe_desc; pipe->status = COMP_STATE_INIT; - pipe->pipe_task.ops = &schedule_mock_ops; + pipe->pipe_task.type = SOF_SCHEDULE_EDF; + + schedulers = calloc(sizeof(struct schedulers), 1); + list_init(&schedulers->list); + + struct schedule_data *sch = calloc(sizeof(struct schedule_data), 1); + + list_init(&sch->list); + sch->type = SOF_SCHEDULE_EDF; + sch->ops = &schedule_mock_ops; + list_item_append(&sch->list, &schedulers->list); struct comp_dev *first = calloc(sizeof(struct comp_dev), 1); diff --git a/test/cmocka/src/audio/pipeline/pipeline_connection_mocks.h b/test/cmocka/src/audio/pipeline/pipeline_connection_mocks.h index 55bfda34462b..fa0e92d28525 100644 --- a/test/cmocka/src/audio/pipeline/pipeline_connection_mocks.h +++ b/test/cmocka/src/audio/pipeline/pipeline_connection_mocks.h @@ -30,7 +30,7 @@ struct pipeline_connect_data *get_standard_connect_objects(void); void cleanup_test_data(struct pipeline_connect_data *data); -static inline void schedule_task_mock_free(struct task *task) +static inline void schedule_task_mock_free(void *data, struct task *task) { task->state = SOF_TASK_STATE_FREE; task->func = NULL; diff --git a/test/cmocka/src/audio/pipeline/pipeline_mocks.c b/test/cmocka/src/audio/pipeline/pipeline_mocks.c index 793fe24f9bdc..a75effb36491 100644 --- a/test/cmocka/src/audio/pipeline/pipeline_mocks.c +++ b/test/cmocka/src/audio/pipeline/pipeline_mocks.c @@ -12,6 +12,12 @@ TRACE_IMPL() struct ipc *_ipc; struct timer *platform_timer; +struct schedulers *schedulers; + +struct schedulers **arch_schedulers_get(void) +{ + return &schedulers; +} void platform_dai_timestamp(struct comp_dev *dai, struct sof_ipc_stream_posn *posn) diff --git a/tools/testbench/CMakeLists.txt b/tools/testbench/CMakeLists.txt index b8e4d087f854..1aae0f6702a7 100644 --- a/tools/testbench/CMakeLists.txt +++ b/tools/testbench/CMakeLists.txt @@ -12,7 +12,6 @@ add_executable(testbench ipc.c schedule.c edf_schedule.c - ll_schedule.c panic.c timer.c topology.c diff --git a/tools/testbench/common_test.c b/tools/testbench/common_test.c index f240fae1637d..1c870029389f 100644 --- a/tools/testbench/common_test.c +++ b/tools/testbench/common_test.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -35,8 +36,8 @@ int tb_pipeline_setup(struct sof *sof) } /* init scheduler */ - if (scheduler_init(sof) < 0) { - fprintf(stderr, "error: scheduler init\n"); + if (scheduler_init_edf(sof) < 0) { + fprintf(stderr, "error: edf scheduler init\n"); return -EINVAL; } diff --git a/tools/testbench/edf_schedule.c b/tools/testbench/edf_schedule.c index bb93a1d87e2b..f992776673eb 100644 --- a/tools/testbench/edf_schedule.c +++ b/tools/testbench/edf_schedule.c @@ -18,17 +18,9 @@ struct edf_schedule_data { uint32_t clock; }; -static struct edf_schedule_data *sch; +struct scheduler_ops schedule_edf_ops; -static void schedule_edf_task_complete(struct task *task); -static void schedule_edf_task(struct task *task, uint64_t start, - uint64_t deadline); -static int schedule_edf_task_init(struct task *task); -static int edf_scheduler_init(struct sof *sof); -static void edf_scheduler_free(void); -static void schedule_edf(void); -static int schedule_edf_task_cancel(struct task *task); -static void schedule_edf_task_free(struct task *task); +static struct edf_schedule_data *sch; static void schedule_edf_task_complete(struct task *task) { @@ -37,9 +29,10 @@ static void schedule_edf_task_complete(struct task *task) } /* schedule task */ -static void schedule_edf_task(struct task *task, uint64_t start, +static void schedule_edf_task(void *data, struct task *task, uint64_t start, uint64_t period) { + struct edf_schedule_data *sch = data; (void)period; list_item_prepend(&task->list, &sch->list); task->state = SOF_TASK_STATE_QUEUED; @@ -50,7 +43,7 @@ static void schedule_edf_task(struct task *task, uint64_t start, schedule_edf_task_complete(task); } -static int schedule_edf_task_init(struct task *task) +static int schedule_edf_task_init(void *data, struct task *task) { struct edf_task_pdata *edf_pdata; @@ -61,37 +54,37 @@ static int schedule_edf_task_init(struct task *task) } /* initialize scheduler */ -static int edf_scheduler_init(struct sof *sof) +int scheduler_init_edf(struct sof *sof) { trace_edf_sch("edf_scheduler_init()"); sch = malloc(sizeof(*sch)); list_init(&sch->list); + scheduler_init(SOF_SCHEDULE_EDF, &schedule_edf_ops, sch); + return 0; } -static void edf_scheduler_free(void) +static void edf_scheduler_free(void *data) { - free(sch); + free(data); } /* The following definitions are to satisfy libsof linker errors */ -static void schedule_edf(void) +static void schedule_edf(void *data) { } -static int schedule_edf_task_cancel(struct task *task) +static void schedule_edf_task_cancel(void *data, struct task *task) { if (task->state == SOF_TASK_STATE_QUEUED) { /* delete task */ task->state = SOF_TASK_STATE_CANCEL; list_item_del(&task->list); } - - return 0; } -static void schedule_edf_task_free(struct task *task) +static void schedule_edf_task_free(void *data, struct task *task) { task->state = SOF_TASK_STATE_FREE; task->func = NULL; @@ -109,7 +102,6 @@ struct scheduler_ops schedule_edf_ops = { .reschedule_task = NULL, .schedule_task_cancel = schedule_edf_task_cancel, .schedule_task_free = schedule_edf_task_free, - .scheduler_init = edf_scheduler_init, .scheduler_free = edf_scheduler_free, .scheduler_run = schedule_edf }; diff --git a/tools/testbench/include/testbench/edf_schedule.h b/tools/testbench/include/testbench/edf_schedule.h deleted file mode 100644 index 7075bdfc7bdb..000000000000 --- a/tools/testbench/include/testbench/edf_schedule.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Bartosz Kokoszko - */ - -#ifndef _INCLUDE_HOST_EDF_SCHEDULE_H_ -#define _INCLUDE_HOST_EDF_SCHEDULE_H_ - -extern struct scheduler_ops schedule_edf_ops; - -#endif /* _INCLUDE_HOST_EDF_SCHEDULE_H_ */ diff --git a/tools/testbench/include/testbench/ll_schedule.h b/tools/testbench/include/testbench/ll_schedule.h deleted file mode 100644 index 4efb8c200e99..000000000000 --- a/tools/testbench/include/testbench/ll_schedule.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Bartosz Kokoszko - */ - -#ifndef _INCLUDE_HOST_LL_SCHEDULE_H_ -#define _INCLUDE_HOST_LL_SCHEDULE_H_ - -extern struct scheduler_ops schedule_ll_ops; - -#endif /* _INCLUDE_HOST_LL_SCHEDULE_H_ */ diff --git a/tools/testbench/ll_schedule.c b/tools/testbench/ll_schedule.c deleted file mode 100644 index 9e1755cfc492..000000000000 --- a/tools/testbench/ll_schedule.c +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Bartosz Kokoszko - -#include -#include -#include -#include - -/* TODO: Make host ll ops implementation */ -struct scheduler_ops schedule_ll_ops = { - .schedule_task = NULL, - .schedule_task_init = NULL, - .schedule_task_running = NULL, - .schedule_task_complete = NULL, - .reschedule_task = NULL, - .schedule_task_cancel = NULL, - .schedule_task_free = NULL, - .scheduler_init = NULL, - .scheduler_free = NULL, - .scheduler_run = NULL -}; diff --git a/tools/testbench/schedule.c b/tools/testbench/schedule.c index 11ee8ee67fb2..db5e5be16170 100644 --- a/tools/testbench/schedule.c +++ b/tools/testbench/schedule.c @@ -11,13 +11,14 @@ #include #include #include -#include "testbench/edf_schedule.h" -#include "testbench/ll_schedule.h" +#include -static const struct scheduler_ops *schedulers[SOF_SCHEDULE_COUNT] = { - &schedule_edf_ops, /* SOF_SCHEDULE_EDF */ - &schedule_ll_ops /* SOF_LL_TASK */ -}; +static struct schedule_data *sch; + +struct schedulers **arch_schedulers_get(void) +{ + return NULL; +} /* testbench work definition */ int schedule_task_init(struct task *task, uint16_t type, uint16_t priority, @@ -31,44 +32,17 @@ int schedule_task_init(struct task *task, uint16_t type, uint16_t priority, task->func = func; task->data = data; - if (schedulers[task->type]->schedule_task_init) - return schedulers[task->type]->schedule_task_init(task); + if (task->type == sch->type && sch->ops->schedule_task_init) + return sch->ops->schedule_task_init(sch->data, task); else return -ENOENT; } -int scheduler_init(struct sof *sof) -{ - int i = 0; - int ret = 0; - - for (i = 0; i < SOF_SCHEDULE_COUNT; i++) { - if (schedulers[i]->scheduler_init) { - ret = schedulers[i]->scheduler_init(sof); - if (ret < 0) - goto out; - } - } -out: - return ret; -} - -void schedule_free(void) -{ - int i; - - for (i = 0; i < SOF_SCHEDULE_COUNT; i++) { - if (schedulers[i]->scheduler_free) - schedulers[i]->scheduler_free(); - } -} - -void schedule(void) +void scheduler_init(int type, const struct scheduler_ops *ops, void *data) { - int i = 0; - - for (i = 0; i < SOF_SCHEDULE_COUNT; i++) { - if (schedulers[i]->scheduler_run) - schedulers[i]->scheduler_run(); - } + sch = malloc(sizeof(*sch)); + list_init(&sch->list); + sch->type = type; + sch->ops = ops; + sch->data = data; }