/* * Copyright 2015 Rockchip Electronics Co. LTD * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define MODULE_TAG "hal_task" #include #include "mpp_mem.h" #include "mpp_list.h" #include "mpp_lock.h" #include "mpp_debug.h" #include "mpp_common.h" #include "hal_task.h" typedef struct HalTaskImpl_t HalTaskImpl; typedef struct HalTaskGroupImpl_t HalTaskGroupImpl; struct HalTaskImpl_t { struct list_head list; HalTaskGroupImpl *group; RK_S32 index; RK_S32 status; void *data; }; struct HalTaskGroupImpl_t { RK_S32 stage_count; RK_S32 task_count; spinlock_t lock; RK_S32 size; RK_S32 aligned_size; struct list_head *list; RK_U32 *count; HalTaskImpl *tasks; }; MPP_RET hal_task_group_init(HalTaskGroup *group, RK_S32 stage_cnt, RK_S32 task_cnt, RK_S32 task_size) { if (NULL == group || stage_cnt < 0 || task_cnt < 0 || task_size < 0) { mpp_err_f("found invalid input group %p stage %d task %d size %d\n", group, stage_cnt, task_cnt, task_size); return MPP_ERR_UNKNOW; } HalTaskGroupImpl *p = NULL; RK_S32 aligned_size = MPP_ALIGN(task_size, sizeof(void *)); do { RK_U8 *buf = NULL; RK_S32 i; p = mpp_calloc_size(HalTaskGroupImpl, sizeof(HalTaskGroupImpl) + (sizeof(HalTaskImpl) + aligned_size) * task_cnt + (sizeof(struct list_head)) * stage_cnt + (sizeof(RK_U32)) * stage_cnt); if (NULL == p) { mpp_err_f("malloc group failed\n"); break; } p->stage_count = stage_cnt; p->task_count = task_cnt; p->size = task_size; p->aligned_size = aligned_size; p->list = (struct list_head *)((HalTaskImpl *)(p + 1)); p->count = (RK_U32 *)(p->list + stage_cnt); p->tasks = (HalTaskImpl *)(p->count + stage_cnt); mpp_spinlock_init(&p->lock); for (i = 0; i < stage_cnt; i++) INIT_LIST_HEAD(&p->list[i]); buf = (RK_U8 *)(p->tasks + task_cnt); for (i = 0; i < task_cnt; i++) { HalTaskImpl *task = &p->tasks[i]; INIT_LIST_HEAD(&task->list); task->index = i; task->group = p; task->status = TASK_IDLE; task->data = buf + i * aligned_size; list_add_tail(&task->list, &p->list[TASK_IDLE]); p->count[TASK_IDLE]++; } *group = p; return MPP_OK; } while (0); MPP_FREE(p); *group = NULL; return MPP_NOK; } MPP_RET hal_task_group_deinit(HalTaskGroup group) { MPP_FREE(group); return MPP_OK; } MPP_RET hal_task_get_hnd(HalTaskGroup group, RK_S32 status, HalTaskHnd *hnd) { if (NULL == group || status >= TASK_BUTT || NULL == hnd) { mpp_err_f("found invaid input group %p status %d hnd %p\n", group, status, hnd); return MPP_ERR_UNKNOW; } *hnd = NULL; HalTaskGroupImpl *p = (HalTaskGroupImpl *)group; struct list_head *list = &p->list[status]; mpp_spinlock_lock(&p->lock); if (list_empty(list)) { mpp_spinlock_unlock(&p->lock); return MPP_NOK; } HalTaskImpl *task = list_entry(list->next, HalTaskImpl, list); mpp_assert(task->status == status); *hnd = task; mpp_spinlock_unlock(&p->lock); return MPP_OK; } MPP_RET hal_task_check_empty(HalTaskGroup group, RK_S32 status) { if (NULL == group || status >= TASK_BUTT) { mpp_err_f("found invaid input group %p status %d \n", group, status); return MPP_ERR_UNKNOW; } HalTaskGroupImpl *p = (HalTaskGroupImpl *)group; struct list_head *list = &p->list[status]; MPP_RET ret; mpp_spinlock_lock(&p->lock); ret = list_empty(list) ? MPP_OK : MPP_NOK; mpp_spinlock_unlock(&p->lock); return ret; } RK_S32 hal_task_get_count(HalTaskGroup group, RK_S32 status) { if (NULL == group || status >= TASK_BUTT) { mpp_err_f("found invaid input group %p status %d\n", group, status); return -1; } HalTaskGroupImpl *p = (HalTaskGroupImpl *)group; RK_S32 count; mpp_spinlock_lock(&p->lock); count = p->count[status]; mpp_spinlock_unlock(&p->lock); return count; } MPP_RET hal_task_hnd_set_status(HalTaskHnd hnd, RK_S32 status) { if (NULL == hnd || status >= TASK_BUTT) { mpp_err_f("found invaid input hnd %p status %d\n", hnd, status); return MPP_ERR_UNKNOW; } HalTaskImpl *impl = (HalTaskImpl *)hnd; HalTaskGroupImpl *group = impl->group; mpp_assert(group); mpp_assert(impl->index < group->task_count); mpp_spinlock_lock(&group->lock); list_del_init(&impl->list); list_add_tail(&impl->list, &group->list[status]); group->count[impl->status]--; group->count[status]++; impl->status = status; mpp_spinlock_unlock(&group->lock); return MPP_OK; } MPP_RET hal_task_hnd_set_info(HalTaskHnd hnd, void *info) { if (NULL == hnd || NULL == info) { mpp_err_f("found invaid input hnd %p info %p\n", hnd, info); return MPP_ERR_UNKNOW; } HalTaskImpl *impl = (HalTaskImpl *)hnd; HalTaskGroupImpl *group = impl->group; mpp_assert(impl->index < group->task_count); mpp_spinlock_lock(&group->lock); memcpy(impl->data, info, group->size); mpp_spinlock_unlock(&group->lock); return MPP_OK; } MPP_RET hal_task_hnd_get_info(HalTaskHnd hnd, void *info) { if (NULL == hnd || NULL == info) { mpp_err_f("found invaid input hnd %p info %p\n", hnd, info); return MPP_ERR_UNKNOW; } HalTaskImpl *impl = (HalTaskImpl *)hnd; HalTaskGroupImpl *group = impl->group; mpp_assert(impl->index < group->task_count); mpp_spinlock_lock(&group->lock); memcpy(info, impl->data, group->size); mpp_spinlock_unlock(&group->lock); return MPP_OK; } void *hal_task_hnd_get_data(HalTaskHnd hnd) { if (NULL == hnd) { mpp_err_f("found invaid input hnd %p\n", hnd); return NULL; } HalTaskImpl *impl = (HalTaskImpl *)hnd; HalTaskGroupImpl *group = impl->group; mpp_assert(impl->index < group->task_count); return impl->data; }