[Cbe-oss-dev] [PATCH 7/10 v2] MARS: workload queue api fix
Kazunori Asayama
asayama at sm.sony.co.jp
Mon Sep 1 12:48:21 EST 2008
Yuji Mano wrote:
> This modifies the internal workload queue API in the host-side library. When
> scheduling a new workload, the workload model may need to initialize parts of
> the workload context once it has been reserved in an available slot of the
> workload queue.
>
> To allow the workload queue to internally handle its own mutex protection of
> each queue block, the workload queue APIs for mars_workload_queue_add,
> mars_workload_queue_remove, and mars_workload_queue_schedule, will each be
> split into 3 separate stages of *_begin/*_end/*_cancel.
>
> *_begin will reserve the workload queue slot and return the pointer to the
> reserved workload context and atomically set its state to "ADDING", "REMOVING",
> or "SCHEDULING" respective to the call.
>
> Between calls from *_begin and *_end, the caller can modify the workload
> context as necessary.
>
> The *_cancel is provided so that if the caller encounters an error in between
> the *_begin and *_end calls it may cancel the add/remove/schedule process
> without calling *_end.
>
> This patch also removes the unnecessary member count inside the workload queue
> header.
>
> Signed-off-by: Yuji Mano <yuji.mano at am.sony.com>
Acked-by: Kazunori Asayama <asayama at sm.sony.co.jp>
>
> ---
> v2:
> - complete change in implementation from v1 patch
> - update patch header for new implementation explanation
>
> include/common/mars/mars_workload_types.h | 12 -
> include/host/mars/mars_workload_queue.h | 32 +++-
> src/host/lib/mars_task.c | 120 +++++++++-------
> src/host/lib/mars_workload_queue.c | 219 +++++++++++++++++++++---------
> src/mpu/kernel/mars_kernel_scheduler.c | 4
> 5 files changed, 257 insertions(+), 130 deletions(-)
>
> --- a/include/common/mars/mars_workload_types.h
> +++ b/include/common/mars/mars_workload_types.h
> @@ -50,10 +50,13 @@ extern "C" {
> #define MARS_WORKLOAD_TYPE_TASK 0x01 /* workload type */
>
> #define MARS_WORKLOAD_STATE_NONE 0x00 /* workload undefined */
> -#define MARS_WORKLOAD_STATE_READY 0x01 /* ready to schedule */
> -#define MARS_WORKLOAD_STATE_WAITING 0x02 /* waiting for sync */
> -#define MARS_WORKLOAD_STATE_RUNNING 0x03 /* currently running */
> -#define MARS_WORKLOAD_STATE_FINISHED 0x04 /* not allow schedule */
> +#define MARS_WORKLOAD_STATE_ADDING 0x01 /* adding now */
> +#define MARS_WORKLOAD_STATE_REMOVING 0x02 /* removing now */
> +#define MARS_WORKLOAD_STATE_SCHEDULING 0x03 /* scheduling now */
> +#define MARS_WORKLOAD_STATE_READY 0x04 /* ready to schedule */
> +#define MARS_WORKLOAD_STATE_WAITING 0x05 /* waiting for sync */
> +#define MARS_WORKLOAD_STATE_RUNNING 0x06 /* currently running */
> +#define MARS_WORKLOAD_STATE_FINISHED 0x07 /* not allow schedule */
>
> #define MARS_WORKLOAD_PRIORITY_MIN 0x00 /* minimum priority */
> #define MARS_WORKLOAD_PRIORITY_MAX 0xff /* maximum priority */
> @@ -84,7 +87,6 @@ struct mars_workload_context {
> struct mars_workload_queue_header {
> uint64_t queue_ea;
> uint64_t context_ea;
> - uint32_t count;
> uint8_t flag;
> } __attribute__((aligned(MARS_WORKLOAD_QUEUE_HEADER_ALIGN)));
>
> --- a/include/host/mars/mars_workload_queue.h
> +++ b/include/host/mars/mars_workload_queue.h
> @@ -46,16 +46,30 @@ extern "C" {
>
> int workload_queue_initialize(struct mars_workload_queue *queue);
> int workload_queue_finalize(struct mars_workload_queue *queue);
> -int workload_queue_add(struct mars_workload_queue *queue, uint16_t *id,
> - struct mars_workload_context *workload, uint8_t type);
> -int workload_queue_remove(struct mars_workload_queue *queue, uint16_t id,
> - struct mars_workload_context *workload);
> -int workload_queue_context(struct mars_workload_queue *queue, uint16_t id,
> +
> +int workload_queue_add_begin(struct mars_workload_queue *queue, uint16_t *id,
> + uint8_t type,
> + struct mars_workload_context **workload);
> +int workload_queue_add_end(struct mars_workload_queue *queue, uint16_t id);
> +int workload_queue_add_cancel(struct mars_workload_queue *queue, uint16_t id);
> +
> +int workload_queue_remove_begin(struct mars_workload_queue *queue, uint16_t id,
> + struct mars_workload_context **workload);
> +int workload_queue_remove_end(struct mars_workload_queue *queue, uint16_t id);
> +int workload_queue_remove_cancel(struct mars_workload_queue *queue,
> + uint16_t id);
> +
> +int workload_queue_schedule_begin(struct mars_workload_queue *queue,
> + uint16_t id, uint8_t priority,
> + struct mars_workload_context **workload);
> +int workload_queue_schedule_end(struct mars_workload_queue *queue, uint16_t id);
> +int workload_queue_schedule_cancel(struct mars_workload_queue *queue,
> + uint16_t id);
> +
> +int workload_queue_wait(struct mars_workload_queue *queue, uint16_t id,
> + struct mars_workload_context **workload);
> +int workload_queue_try_wait(struct mars_workload_queue *queue, uint16_t id,
> struct mars_workload_context **workload);
> -int workload_queue_schedule(struct mars_workload_queue *queue, uint16_t id,
> - uint8_t priority);
> -int workload_queue_wait(struct mars_workload_queue *queue, uint16_t id);
> -int workload_queue_try_wait(struct mars_workload_queue *queue, uint16_t id);
> int workload_queue_signal_send(struct mars_workload_queue *queue, uint16_t id);
>
> #if defined(__cplusplus)
> --- a/src/host/lib/mars_task.c
> +++ b/src/host/lib/mars_task.c
> @@ -54,56 +54,67 @@ int mars_task_initialize(struct mars_con
> MARS_CHECK_RET(params, MARS_ERROR_NULL);
>
> int ret;
> - struct mars_task_context task;
> + struct mars_task_context *task;
>
> /* initialize task context */
> - task.id.mars_context_ea = (uint64_t)(uintptr_t)mars;
> -
> - /* parse the elf parameter */
> - ret = mars_elf_parse(params->elf_image, &task.exec, &task.exec_size,
> - &task.bss_size, &task.vaddr, &task.entry);
> - MARS_CHECK_RET(ret == MARS_SUCCESS, ret);
> + id->mars_context_ea = (uint64_t)(uintptr_t)mars;
>
> /* copy the task name into task id */
> if (params->name) {
> MARS_CHECK_RET(strlen(params->name) < MARS_TASK_NAME_LEN_MAX,
> MARS_ERROR_PARAMS);
> - strcpy((char *)&task.id.name, params->name);
> + strcpy((char *)&id->name, params->name);
> }
>
> + /* begin process to add the task to the workload queue */
> + ret = workload_queue_add_begin(mars->workload_queue, &id->workload_id,
> + MARS_WORKLOAD_TYPE_TASK,
> + (struct mars_workload_context **)&task);
> + MARS_CHECK_RET(ret == MARS_SUCCESS, ret);
> +
> + /* initialize task specific id */
> + memcpy(&task->id, id, sizeof(struct mars_task_id));
> +
> + /* parse the elf parameter */
> + ret = mars_elf_parse(params->elf_image, &task->exec, &task->exec_size,
> + &task->bss_size, &task->vaddr, &task->entry);
> + MARS_CHECK_CLEANUP_RET(ret == MARS_SUCCESS,
> + workload_queue_add_cancel(mars->workload_queue,
> + id->workload_id),
> + ret);
> +
> /* allocate the task context area if specified */
> if (params->context_save_size) {
> - MARS_CHECK_RET(params->context_save_size <=
> - MARS_TASK_CONTEXT_SAVE_SIZE_MAX, MARS_ERROR_PARAMS);
> + MARS_CHECK_CLEANUP_RET(params->context_save_size <=
> + MARS_TASK_CONTEXT_SAVE_SIZE_MAX,
> + workload_queue_add_cancel(mars->workload_queue,
> + id->workload_id),
> + MARS_ERROR_PARAMS);
>
> - task.context_save_size =
> + task->context_save_size =
> params->context_save_size;
> - task.context_save_area = (uint64_t)(uintptr_t)
> + task->context_save_area = (uint64_t)(uintptr_t)
> memalign(MARS_TASK_CONTEXT_SAVE_ALIGN,
> - task.context_save_size);
> + task->context_save_size);
>
> - MARS_CHECK_RET(task.context_save_area, MARS_ERROR_MEMORY);
> + MARS_CHECK_CLEANUP_RET(task->context_save_area,
> + workload_queue_add_cancel(mars->workload_queue,
> + id->workload_id),
> + MARS_ERROR_MEMORY);
> } else {
> - task.context_save_size = 0;
> - task.context_save_area = 0;
> + task->context_save_size = 0;
> + task->context_save_area = 0;
> }
>
> - mars_mutex_lock(mars->mutex);
> -
> - /* add the task to the workload queue */
> - ret = workload_queue_add(mars->workload_queue, &task.id.workload_id,
> - (struct mars_workload_context *)&task,
> - MARS_WORKLOAD_TYPE_TASK);
> + /* end process to add the task to the workload queue */
> + ret = workload_queue_add_end(mars->workload_queue, id->workload_id);
> MARS_CHECK_CLEANUP_RET(ret == MARS_SUCCESS,
> - free((void *)task.context_save_area), ret);
> - MARS_PRINT_TASK_CONTEXT(&task);
> -
> - /* copy the task id into return id */
> - *id = task.id;
> -
> - mars_mutex_unlock(mars->mutex);
> + workload_queue_add_cancel(mars->workload_queue,
> + id->workload_id),
> + ret);
>
> MARS_PRINT("Initialize Task Context %d\n", task->id.workload_id);
> + MARS_PRINT_TASK_CONTEXT(&task);
>
> return MARS_SUCCESS;
> }
> @@ -115,23 +126,23 @@ int mars_task_finalize(struct mars_task_
> MARS_CHECK_RET(id->workload_id < MARS_WORKLOAD_MAX, MARS_ERROR_PARAMS);
>
> int ret;
> + struct mars_task_context *task;
> struct mars_context *mars = (struct mars_context *)id->mars_context_ea;
> - struct mars_task_context task;
>
> - mars_mutex_lock(mars->mutex);
> -
> - /* remove the task from the workload queue */
> - ret = workload_queue_remove(mars->workload_queue, id->workload_id,
> - (struct mars_workload_context *)&task);
> + /* begin process to remove the task from the workload queue */
> + ret = workload_queue_remove_begin(mars->workload_queue, id->workload_id,
> + (struct mars_workload_context **)&task);
> MARS_CHECK_RET(ret == MARS_SUCCESS, ret);
>
> /* free the allocated task context area if it has one */
> - if (task.context_save_size)
> - free((void *)task.context_save_area);
> + if (task->context_save_size)
> + free((void *)task->context_save_area);
>
> - mars_mutex_unlock(mars->mutex);
> + /* end process to remove the task from the workload queue */
> + ret = workload_queue_remove_end(mars->workload_queue, id->workload_id);
> + MARS_CHECK_RET(ret == MARS_SUCCESS, ret);
>
> - MARS_PRINT("Finalize Task Context %d\n", task.id.workload_id);
> + MARS_PRINT("Finalize Task Context %d\n", id->workload_id);
>
> return MARS_SUCCESS;
> }
> @@ -145,14 +156,13 @@ int mars_task_schedule(struct mars_task_
> MARS_CHECK_RET(id->workload_id < MARS_WORKLOAD_MAX, MARS_ERROR_PARAMS);
>
> int ret;
> + struct mars_task_context *task;
> struct mars_context *mars = (struct mars_context *)id->mars_context_ea;
> - struct mars_task_context *task = NULL;
>
> - mars_mutex_lock(mars->mutex);
> -
> - /* get workload context pointer from the workload queue */
> - ret = workload_queue_context(mars->workload_queue, id->workload_id,
> - (struct mars_workload_context **)&task);
> + /* begin process to schedule the workload in the workload queue */
> + ret = workload_queue_schedule_begin(mars->workload_queue,
> + id->workload_id, priority,
> + (struct mars_workload_context **)&task);
> MARS_CHECK_RET(ret == MARS_SUCCESS, ret);
>
> /* initialize task specific context variables */
> @@ -160,14 +170,12 @@ int mars_task_schedule(struct mars_task_
> if (args)
> memcpy(&task->args, args, sizeof(struct mars_task_args));
>
> - /* schedule the workload in the workload queue */
> - ret = workload_queue_schedule(mars->workload_queue, id->workload_id,
> - priority);
> + /* end process to schedule the workload in the workload queue */
> + ret = workload_queue_schedule_end(mars->workload_queue,
> + id->workload_id);
> MARS_CHECK_RET(ret == MARS_SUCCESS, ret);
>
> - mars_mutex_unlock(mars->mutex);
> -
> - MARS_PRINT("Schedule Task Context %d\n", task->id.workload_id);
> + MARS_PRINT("Schedule Task Context %d\n", id->workload_id);
>
> return MARS_SUCCESS;
> }
> @@ -179,9 +187,12 @@ int mars_task_wait(struct mars_task_id *
> MARS_CHECK_RET(id->workload_id < MARS_WORKLOAD_MAX, MARS_ERROR_PARAMS);
>
> int ret;
> + struct mars_task_context *task;
> struct mars_context *mars = (struct mars_context *)id->mars_context_ea;
>
> - ret = workload_queue_wait(mars->workload_queue, id->workload_id);
> + /* blocking wait for workload completion */
> + ret = workload_queue_wait(mars->workload_queue, id->workload_id,
> + (struct mars_workload_context **)&task);
> MARS_CHECK_RET(ret == MARS_SUCCESS, ret);
>
> return MARS_SUCCESS;
> @@ -194,9 +205,12 @@ int mars_task_try_wait(struct mars_task_
> MARS_CHECK_RET(id->workload_id < MARS_WORKLOAD_MAX, MARS_ERROR_PARAMS);
>
> int ret;
> + struct mars_task_context *task;
> struct mars_context *mars = (struct mars_context *)id->mars_context_ea;
>
> - ret = workload_queue_try_wait(mars->workload_queue, id->workload_id);
> + /* non-blocking wait for workload completion */
> + ret = workload_queue_try_wait(mars->workload_queue, id->workload_id,
> + (struct mars_workload_context **)&task);
> MARS_CHECK_RET(ret == MARS_SUCCESS, ret);
>
> return MARS_SUCCESS;
> --- a/src/host/lib/mars_workload_queue.c
> +++ b/src/host/lib/mars_workload_queue.c
> @@ -52,7 +52,6 @@ int workload_queue_initialize(struct mar
>
> queue->header.queue_ea = (uint64_t)(uintptr_t)queue;
> queue->header.context_ea = (uint64_t)(uintptr_t)&queue->context;
> - queue->header.count = 0;
> queue->header.flag = MARS_FLAG_NONE;
>
> return MARS_SUCCESS;
> @@ -61,68 +60,109 @@ int workload_queue_initialize(struct mar
> int workload_queue_finalize(struct mars_workload_queue *queue)
> {
> MARS_CHECK_RET(queue, MARS_ERROR_NULL);
> - MARS_CHECK_RET(!queue->header.count, MARS_ERROR_STATE);
> +
> + int block;
> + int index;
> +
> + uint16_t id = 0;
> +
> + /* check for any tasks left in workload queue */
> + while (id < MARS_WORKLOAD_MAX) {
> + block = id / MARS_WORKLOAD_PER_BLOCK;
> + index = id % MARS_WORKLOAD_PER_BLOCK;
> +
> + if (queue->block[block].bits[index].state !=
> + MARS_WORKLOAD_STATE_NONE)
> + break;
> +
> + id++;
> + }
> +
> + /* found some task left in workload queue */
> + MARS_CHECK_RET(id < MARS_WORKLOAD_MAX, MARS_ERROR_STATE);
>
> queue->header.flag = MARS_FLAG_EXIT;
>
> return MARS_SUCCESS;
> }
>
> -int workload_queue_add(struct mars_workload_queue *queue, uint16_t *id,
> - struct mars_workload_context *workload, uint8_t type)
> +int workload_queue_add_begin(struct mars_workload_queue *queue, uint16_t *id,
> + uint8_t type,
> + struct mars_workload_context **workload)
> {
> MARS_CHECK_RET(queue, MARS_ERROR_NULL);
> - MARS_CHECK_RET(workload, MARS_ERROR_NULL);
> MARS_CHECK_RET(id, MARS_ERROR_NULL);
> MARS_CHECK_RET(type == MARS_WORKLOAD_TYPE_TASK, MARS_ERROR_PARAMS);
> - MARS_CHECK_RET(queue->header.count < MARS_WORKLOAD_MAX,
> - MARS_ERROR_LIMIT);
>
> int block = 0;
> int index = 0;
>
> - /* search through workload queue for open slot */
> - if (queue->header.count) {
> - int i;
> - int j;
> -
> - for (i = 0; i < MARS_WORKLOAD_NUM_BLOCKS; i++) {
> - for (j = 0; j < MARS_WORKLOAD_PER_BLOCK; j++) {
> - if (queue->block[i].bits[j].state ==
> - MARS_WORKLOAD_STATE_NONE) {
> - block = i;
> - index = j;
> - i = MARS_WORKLOAD_NUM_BLOCKS;
> - j = MARS_WORKLOAD_PER_BLOCK;
> - }
> - }
> - }
> - }
> + *id = 0;
> +
> + /* find first available empty slot */
> + while (*id < MARS_WORKLOAD_MAX) {
> + block = *id / MARS_WORKLOAD_PER_BLOCK;
> + index = *id % MARS_WORKLOAD_PER_BLOCK;
> +
> + if (queue->block[block].bits[index].state ==
> + MARS_WORKLOAD_STATE_NONE)
> + break;
>
> - /* set return id of added workload context */
> - *id = MARS_WORKLOAD_PER_BLOCK * block + index;
> + (*id)++;
> + }
>
> - /* copy workload context into workload queue */
> - memcpy(&queue->context[*id], workload,
> - sizeof(struct mars_workload_context));
> + /* no empty slot found - workload queue is full */
> + MARS_CHECK_RET(*id < MARS_WORKLOAD_MAX, MARS_ERROR_LIMIT);
>
> - /* update workload queue header info */
> + /* set type and set state to adding */
> queue->block[block].bits[index].type = type;
> + queue->block[block].bits[index].state = MARS_WORKLOAD_STATE_ADDING;
> +
> + /* if requested set workload context pointer to return */
> + if (workload)
> + *workload = &queue->context[*id];
> +
> + return MARS_SUCCESS;
> +}
> +
> +int workload_queue_add_end(struct mars_workload_queue *queue, uint16_t id)
> +{
> + MARS_CHECK_RET(queue, MARS_ERROR_NULL);
> + MARS_CHECK_RET(id < MARS_WORKLOAD_MAX, MARS_ERROR_PARAMS);
> +
> + int block = id / MARS_WORKLOAD_PER_BLOCK;
> + int index = id % MARS_WORKLOAD_PER_BLOCK;
> +
> + MARS_CHECK_RET(queue->block[block].bits[index].state ==
> + MARS_WORKLOAD_STATE_ADDING, MARS_ERROR_STATE);
> +
> + /* reset workload queue bits and set state to finished state */
> queue->block[block].bits[index].state = MARS_WORKLOAD_STATE_FINISHED;
> - queue->block[block].bits[index].priority = MARS_WORKLOAD_PRIORITY_MIN;
> - queue->block[block].bits[index].counter = MARS_WORKLOAD_COUNTER_MIN;
> - queue->block[block].bits[index].signal = MARS_WORKLOAD_SIGNAL_OFF;
> - queue->block[block].bits[index].wait = MARS_WORKLOAD_ID_NONE;
> - queue->header.count++;
>
> return MARS_SUCCESS;
> }
>
> -int workload_queue_remove(struct mars_workload_queue *queue, uint16_t id,
> - struct mars_workload_context *workload)
> +int workload_queue_add_cancel(struct mars_workload_queue *queue, uint16_t id)
> +{
> + MARS_CHECK_RET(queue, MARS_ERROR_NULL);
> + MARS_CHECK_RET(id < MARS_WORKLOAD_MAX, MARS_ERROR_PARAMS);
> +
> + int block = id / MARS_WORKLOAD_PER_BLOCK;
> + int index = id % MARS_WORKLOAD_PER_BLOCK;
> +
> + MARS_CHECK_RET(queue->block[block].bits[index].state ==
> + MARS_WORKLOAD_STATE_ADDING, MARS_ERROR_STATE);
> +
> + /* set state back to none state */
> + queue->block[block].bits[index].state = MARS_WORKLOAD_STATE_NONE;
> +
> + return MARS_SUCCESS;
> +}
> +
> +int workload_queue_remove_begin(struct mars_workload_queue *queue, uint16_t id,
> + struct mars_workload_context **workload)
> {
> MARS_CHECK_RET(queue, MARS_ERROR_NULL);
> - MARS_CHECK_RET(workload, MARS_ERROR_NULL);
> MARS_CHECK_RET(id < MARS_WORKLOAD_MAX, MARS_ERROR_PARAMS);
>
> int block = id / MARS_WORKLOAD_PER_BLOCK;
> @@ -131,42 +171,53 @@ int workload_queue_remove(struct mars_wo
> MARS_CHECK_RET(queue->block[block].bits[index].state ==
> MARS_WORKLOAD_STATE_FINISHED, MARS_ERROR_STATE);
>
> - /* copy workload context out from workload queue */
> - memcpy(workload, &queue->context[id],
> - sizeof(struct mars_workload_context));
> + /* set state to removing */
> + queue->block[block].bits[index].state = MARS_WORKLOAD_STATE_REMOVING;
> +
> + /* if requested set workload context pointer to return */
> + if (workload)
> + *workload = &queue->context[id];
> +
> + return MARS_SUCCESS;
> +}
> +
> +int workload_queue_remove_end(struct mars_workload_queue *queue, uint16_t id)
> +{
> + MARS_CHECK_RET(queue, MARS_ERROR_NULL);
> + MARS_CHECK_RET(id < MARS_WORKLOAD_MAX, MARS_ERROR_PARAMS);
> +
> + int block = id / MARS_WORKLOAD_PER_BLOCK;
> + int index = id % MARS_WORKLOAD_PER_BLOCK;
> +
> + MARS_CHECK_RET(queue->block[block].bits[index].state ==
> + MARS_WORKLOAD_STATE_REMOVING, MARS_ERROR_STATE);
>
> - /* update workload queue info */
> + /* set state to none */
> queue->block[block].bits[index].type = MARS_WORKLOAD_TYPE_NONE;
> - queue->block[block].bits[index].state = MARS_WORKLOAD_STATE_NONE;
> - queue->block[block].bits[index].priority = MARS_WORKLOAD_PRIORITY_MIN;
> - queue->block[block].bits[index].counter = MARS_WORKLOAD_COUNTER_MIN;
> - queue->block[block].bits[index].signal = MARS_WORKLOAD_SIGNAL_OFF;
> - queue->block[block].bits[index].wait = MARS_WORKLOAD_ID_NONE;
> - queue->header.count--;
>
> return MARS_SUCCESS;
> }
>
> -int workload_queue_context(struct mars_workload_queue *queue, uint16_t id,
> - struct mars_workload_context **workload)
> +int workload_queue_remove_cancel(struct mars_workload_queue *queue, uint16_t id)
> {
> MARS_CHECK_RET(queue, MARS_ERROR_NULL);
> - MARS_CHECK_RET(workload, MARS_ERROR_NULL);
> MARS_CHECK_RET(id < MARS_WORKLOAD_MAX, MARS_ERROR_PARAMS);
>
> int block = id / MARS_WORKLOAD_PER_BLOCK;
> int index = id % MARS_WORKLOAD_PER_BLOCK;
>
> - MARS_CHECK_RET(queue->block[block].bits[index].state !=
> - MARS_WORKLOAD_STATE_NONE, MARS_ERROR_STATE);
> + MARS_CHECK_RET(queue->block[block].bits[index].state ==
> + MARS_WORKLOAD_STATE_REMOVING, MARS_ERROR_STATE);
>
> - *workload = &queue->context[id];
> + /* set state back to finished */
> + queue->block[block].bits[index].type = MARS_WORKLOAD_STATE_FINISHED;
>
> return MARS_SUCCESS;
> }
>
> -int workload_queue_schedule(struct mars_workload_queue *queue, uint16_t id,
> - uint8_t priority)
> +int workload_queue_schedule_begin(struct mars_workload_queue *queue,
> + uint16_t id, uint8_t priority,
> + struct mars_workload_context **workload)
> {
> MARS_CHECK_RET(queue, MARS_ERROR_NULL);
> MARS_CHECK_RET(id < MARS_WORKLOAD_MAX, MARS_ERROR_PARAMS);
> @@ -177,16 +228,57 @@ int workload_queue_schedule(struct mars_
> MARS_CHECK_RET(queue->block[block].bits[index].state ==
> MARS_WORKLOAD_STATE_FINISHED, MARS_ERROR_STATE);
>
> - queue->block[block].bits[index].state = MARS_WORKLOAD_STATE_READY;
> + /* reset workload queue bits and set state to scheduling */
> + queue->block[block].bits[index].state = MARS_WORKLOAD_STATE_SCHEDULING;
> queue->block[block].bits[index].priority = priority;
> queue->block[block].bits[index].counter = MARS_WORKLOAD_COUNTER_MIN;
> queue->block[block].bits[index].signal = MARS_WORKLOAD_SIGNAL_OFF;
> queue->block[block].bits[index].wait = MARS_WORKLOAD_ID_NONE;
>
> + /* if requested set workload context pointer to return */
> + if (workload)
> + *workload = &queue->context[id];
> +
> + return MARS_SUCCESS;
> +}
> +
> +int workload_queue_schedule_end(struct mars_workload_queue *queue, uint16_t id)
> +{
> + MARS_CHECK_RET(queue, MARS_ERROR_NULL);
> + MARS_CHECK_RET(id < MARS_WORKLOAD_MAX, MARS_ERROR_PARAMS);
> +
> + int block = id / MARS_WORKLOAD_PER_BLOCK;
> + int index = id % MARS_WORKLOAD_PER_BLOCK;
> +
> + MARS_CHECK_RET(queue->block[block].bits[index].state ==
> + MARS_WORKLOAD_STATE_SCHEDULING, MARS_ERROR_STATE);
> +
> + /* set state to ready */
> + queue->block[block].bits[index].state = MARS_WORKLOAD_STATE_READY;
> +
> + return MARS_SUCCESS;
> +}
> +
> +int workload_queue_schedule_cancel(struct mars_workload_queue *queue,
> + uint16_t id)
> +{
> + MARS_CHECK_RET(queue, MARS_ERROR_NULL);
> + MARS_CHECK_RET(id < MARS_WORKLOAD_MAX, MARS_ERROR_PARAMS);
> +
> + int block = id / MARS_WORKLOAD_PER_BLOCK;
> + int index = id % MARS_WORKLOAD_PER_BLOCK;
> +
> + MARS_CHECK_RET(queue->block[block].bits[index].state ==
> + MARS_WORKLOAD_STATE_SCHEDULING, MARS_ERROR_STATE);
> +
> + /* set state back to finished */
> + queue->block[block].bits[index].state = MARS_WORKLOAD_STATE_FINISHED;
> +
> return MARS_SUCCESS;
> }
>
> -int workload_queue_wait(struct mars_workload_queue *queue, uint16_t id)
> +int workload_queue_wait(struct mars_workload_queue *queue, uint16_t id,
> + struct mars_workload_context **workload)
> {
> MARS_CHECK_RET(queue, MARS_ERROR_NULL);
> MARS_CHECK_RET(id < MARS_WORKLOAD_MAX, MARS_ERROR_PARAMS);
> @@ -201,10 +293,15 @@ int workload_queue_wait(struct mars_work
> MARS_WORKLOAD_STATE_FINISHED)
> sched_yield();
>
> + /* if requested set workload context pointer to return */
> + if (workload)
> + *workload = &queue->context[id];
> +
> return MARS_SUCCESS;
> }
>
> -int workload_queue_try_wait(struct mars_workload_queue *queue, uint16_t id)
> +int workload_queue_try_wait(struct mars_workload_queue *queue, uint16_t id,
> + struct mars_workload_context **workload)
> {
> MARS_CHECK_RET(queue, MARS_ERROR_NULL);
> MARS_CHECK_RET(id < MARS_WORKLOAD_MAX, MARS_ERROR_PARAMS);
> @@ -219,6 +316,10 @@ int workload_queue_try_wait(struct mars_
> MARS_WORKLOAD_STATE_FINISHED)
> return MARS_ERROR_BUSY;
>
> + /* if requested set workload context pointer to return */
> + if (workload)
> + *workload = &queue->context[id];
> +
> return MARS_SUCCESS;
> }
>
> --- a/src/mpu/kernel/mars_kernel_scheduler.c
> +++ b/src/mpu/kernel/mars_kernel_scheduler.c
> @@ -271,10 +271,6 @@ int scheduler(void)
> if (queue_header.flag == MARS_FLAG_EXIT)
> return MARS_KERNEL_STATUS_EXIT;
>
> - /* queue empty so return idle*/
> - if (!queue_header.count)
> - return MARS_KERNEL_STATUS_IDLE;
> -
> /* reserve next workload to run or return idle status if none found */
> status = reserve_workload();
>
>
>
>
--
(ASAYAMA Kazunori
(asayama at sm.sony.co.jp))
t
More information about the cbe-oss-dev
mailing list