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