1 /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2 /*
3 * Copyright (c) 2015 Rockchip Electronics Co., Ltd.
4 */
5
6 #define MODULE_TAG "hal_task"
7
8 #include <string.h>
9
10 #include "mpp_mem.h"
11 #include "mpp_list.h"
12 #include "mpp_lock.h"
13 #include "mpp_debug.h"
14 #include "mpp_common.h"
15
16 #include "hal_task.h"
17
18 typedef struct HalTaskImpl_t HalTaskImpl;
19 typedef struct HalTaskGroupImpl_t HalTaskGroupImpl;
20
21 struct HalTaskImpl_t {
22 struct list_head list;
23 HalTaskGroupImpl *group;
24 RK_S32 index;
25 RK_S32 status;
26 void *data;
27 };
28
29 struct HalTaskGroupImpl_t {
30 RK_S32 stage_count;
31 RK_S32 task_count;
32
33 spinlock_t lock;
34
35 RK_S32 size;
36 RK_S32 aligned_size;
37
38 struct list_head *list;
39 RK_U32 *count;
40 HalTaskImpl *tasks;
41 };
42
hal_task_group_init(HalTaskGroup * group,RK_S32 stage_cnt,RK_S32 task_cnt,RK_S32 task_size)43 MPP_RET hal_task_group_init(HalTaskGroup *group, RK_S32 stage_cnt, RK_S32 task_cnt, RK_S32 task_size)
44 {
45 if (NULL == group || stage_cnt < 0 || task_cnt < 0 || task_size < 0) {
46 mpp_err_f("found invalid input group %p stage %d task %d size %d\n",
47 group, stage_cnt, task_cnt, task_size);
48 return MPP_ERR_UNKNOW;
49 }
50
51 HalTaskGroupImpl *p = NULL;
52 RK_S32 aligned_size = MPP_ALIGN(task_size, sizeof(void *));
53
54 do {
55 RK_U8 *buf = NULL;
56 RK_S32 i;
57
58 p = mpp_calloc_size(HalTaskGroupImpl, sizeof(HalTaskGroupImpl) +
59 (sizeof(HalTaskImpl) + aligned_size) * task_cnt +
60 (sizeof(struct list_head)) * stage_cnt +
61 (sizeof(RK_U32)) * stage_cnt);
62 if (NULL == p) {
63 mpp_err_f("malloc group failed\n");
64 break;
65 }
66
67 p->stage_count = stage_cnt;
68 p->task_count = task_cnt;
69 p->size = task_size;
70 p->aligned_size = aligned_size;
71 p->list = (struct list_head *)((HalTaskImpl *)(p + 1));
72 p->count = (RK_U32 *)(p->list + stage_cnt);
73 p->tasks = (HalTaskImpl *)(p->count + stage_cnt);
74
75 mpp_spinlock_init(&p->lock);
76
77 for (i = 0; i < stage_cnt; i++)
78 INIT_LIST_HEAD(&p->list[i]);
79
80 buf = (RK_U8 *)(p->tasks + task_cnt);
81
82 for (i = 0; i < task_cnt; i++) {
83 HalTaskImpl *task = &p->tasks[i];
84
85 INIT_LIST_HEAD(&task->list);
86 task->index = i;
87 task->group = p;
88 task->status = TASK_IDLE;
89 task->data = buf + i * aligned_size;
90 list_add_tail(&task->list, &p->list[TASK_IDLE]);
91 p->count[TASK_IDLE]++;
92 }
93 *group = p;
94 return MPP_OK;
95 } while (0);
96
97 MPP_FREE(p);
98
99 *group = NULL;
100 return MPP_NOK;
101 }
102
hal_task_group_deinit(HalTaskGroup group)103 MPP_RET hal_task_group_deinit(HalTaskGroup group)
104 {
105 MPP_FREE(group);
106 return MPP_OK;
107 }
108
hal_task_get_hnd(HalTaskGroup group,RK_S32 status,HalTaskHnd * hnd)109 MPP_RET hal_task_get_hnd(HalTaskGroup group, RK_S32 status, HalTaskHnd *hnd)
110 {
111 if (NULL == group || status >= TASK_BUTT || NULL == hnd) {
112 mpp_err_f("found invaid input group %p status %d hnd %p\n", group, status, hnd);
113 return MPP_ERR_UNKNOW;
114 }
115
116 *hnd = NULL;
117 HalTaskGroupImpl *p = (HalTaskGroupImpl *)group;
118 struct list_head *list = &p->list[status];
119
120 mpp_spinlock_lock(&p->lock);
121 if (list_empty(list)) {
122 mpp_spinlock_unlock(&p->lock);
123 return MPP_NOK;
124 }
125
126 HalTaskImpl *task = list_entry(list->next, HalTaskImpl, list);
127 mpp_assert(task->status == status);
128 *hnd = task;
129 mpp_spinlock_unlock(&p->lock);
130 return MPP_OK;
131 }
132
hal_task_check_empty(HalTaskGroup group,RK_S32 status)133 MPP_RET hal_task_check_empty(HalTaskGroup group, RK_S32 status)
134 {
135 if (NULL == group || status >= TASK_BUTT) {
136 mpp_err_f("found invaid input group %p status %d \n", group, status);
137 return MPP_ERR_UNKNOW;
138 }
139
140 HalTaskGroupImpl *p = (HalTaskGroupImpl *)group;
141 struct list_head *list = &p->list[status];
142 MPP_RET ret;
143
144 mpp_spinlock_lock(&p->lock);
145 ret = list_empty(list) ? MPP_OK : MPP_NOK;
146 mpp_spinlock_unlock(&p->lock);
147
148 return ret;
149 }
150
hal_task_get_count(HalTaskGroup group,RK_S32 status)151 RK_S32 hal_task_get_count(HalTaskGroup group, RK_S32 status)
152 {
153 if (NULL == group || status >= TASK_BUTT) {
154 mpp_err_f("found invaid input group %p status %d\n", group, status);
155 return -1;
156 }
157
158 HalTaskGroupImpl *p = (HalTaskGroupImpl *)group;
159 RK_S32 count;
160
161 mpp_spinlock_lock(&p->lock);
162 count = p->count[status];
163 mpp_spinlock_unlock(&p->lock);
164
165 return count;
166 }
167
hal_task_hnd_set_status(HalTaskHnd hnd,RK_S32 status)168 MPP_RET hal_task_hnd_set_status(HalTaskHnd hnd, RK_S32 status)
169 {
170 if (NULL == hnd || status >= TASK_BUTT) {
171 mpp_err_f("found invaid input hnd %p status %d\n", hnd, status);
172 return MPP_ERR_UNKNOW;
173 }
174
175 HalTaskImpl *impl = (HalTaskImpl *)hnd;
176 HalTaskGroupImpl *group = impl->group;
177
178 mpp_assert(group);
179 mpp_assert(impl->index < group->task_count);
180
181 mpp_spinlock_lock(&group->lock);
182 list_del_init(&impl->list);
183 list_add_tail(&impl->list, &group->list[status]);
184 group->count[impl->status]--;
185 group->count[status]++;
186 impl->status = status;
187 mpp_spinlock_unlock(&group->lock);
188
189 return MPP_OK;
190 }
191
hal_task_hnd_set_info(HalTaskHnd hnd,void * info)192 MPP_RET hal_task_hnd_set_info(HalTaskHnd hnd, void *info)
193 {
194 if (NULL == hnd || NULL == info) {
195 mpp_err_f("found invaid input hnd %p info %p\n", hnd, info);
196 return MPP_ERR_UNKNOW;
197 }
198
199 HalTaskImpl *impl = (HalTaskImpl *)hnd;
200 HalTaskGroupImpl *group = impl->group;
201
202 mpp_assert(impl->index < group->task_count);
203
204 mpp_spinlock_lock(&group->lock);
205 memcpy(impl->data, info, group->size);
206 mpp_spinlock_unlock(&group->lock);
207
208 return MPP_OK;
209 }
210
hal_task_hnd_get_info(HalTaskHnd hnd,void * info)211 MPP_RET hal_task_hnd_get_info(HalTaskHnd hnd, void *info)
212 {
213 if (NULL == hnd || NULL == info) {
214 mpp_err_f("found invaid input hnd %p info %p\n", hnd, info);
215 return MPP_ERR_UNKNOW;
216 }
217
218 HalTaskImpl *impl = (HalTaskImpl *)hnd;
219 HalTaskGroupImpl *group = impl->group;
220
221 mpp_assert(impl->index < group->task_count);
222
223 mpp_spinlock_lock(&group->lock);
224 memcpy(info, impl->data, group->size);
225 mpp_spinlock_unlock(&group->lock);
226
227 return MPP_OK;
228 }
229
hal_task_hnd_get_data(HalTaskHnd hnd)230 void *hal_task_hnd_get_data(HalTaskHnd hnd)
231 {
232 if (NULL == hnd) {
233 mpp_err_f("found invaid input hnd %p\n", hnd);
234 return NULL;
235 }
236
237 HalTaskImpl *impl = (HalTaskImpl *)hnd;
238 HalTaskGroupImpl *group = impl->group;
239
240 mpp_assert(impl->index < group->task_count);
241
242 return impl->data;
243 }
244