xref: /rockchip-linux_mpp/mpp/hal/hal_task.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
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