1*437bfbebSnyanmisaka /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2*437bfbebSnyanmisaka /*
3*437bfbebSnyanmisaka * Copyright (c) 2015 Rockchip Electronics Co., Ltd.
4*437bfbebSnyanmisaka */
5*437bfbebSnyanmisaka
6*437bfbebSnyanmisaka #define MODULE_TAG "mpp_buffer"
7*437bfbebSnyanmisaka
8*437bfbebSnyanmisaka #include <string.h>
9*437bfbebSnyanmisaka
10*437bfbebSnyanmisaka #include "mpp_env.h"
11*437bfbebSnyanmisaka #include "mpp_hash.h"
12*437bfbebSnyanmisaka #include "mpp_lock.h"
13*437bfbebSnyanmisaka #include "mpp_time.h"
14*437bfbebSnyanmisaka #include "mpp_debug.h"
15*437bfbebSnyanmisaka #include "mpp_thread.h"
16*437bfbebSnyanmisaka #include "mpp_mem_pool.h"
17*437bfbebSnyanmisaka #include "mpp_singleton.h"
18*437bfbebSnyanmisaka
19*437bfbebSnyanmisaka #include "mpp_buffer_impl.h"
20*437bfbebSnyanmisaka
21*437bfbebSnyanmisaka #define MAX_GROUP_BIT 8
22*437bfbebSnyanmisaka #define MAX_MISC_GROUP_BIT 3
23*437bfbebSnyanmisaka #define BUFFER_OPS_MAX_COUNT 1024
24*437bfbebSnyanmisaka #define MPP_ALLOCATOR_WITH_FLAG_NUM 8
25*437bfbebSnyanmisaka
26*437bfbebSnyanmisaka /* NOTE: user may call buffer / buf_grp deinit after buffer service deinited */
27*437bfbebSnyanmisaka typedef enum MppBufSrvStatus_e {
28*437bfbebSnyanmisaka MPP_BUF_SRV_UNINITED = -1,
29*437bfbebSnyanmisaka MPP_BUF_SRV_NORMAL = 0,
30*437bfbebSnyanmisaka MPP_BUF_SRV_FINALIZED = 1,
31*437bfbebSnyanmisaka MPP_BUF_SRV_BUTT,
32*437bfbebSnyanmisaka } MppBufSrvStatus;
33*437bfbebSnyanmisaka
34*437bfbebSnyanmisaka #define SEARCH_GROUP_BY_ID(srv, id) (get_group_by_id(srv, id))
35*437bfbebSnyanmisaka
36*437bfbebSnyanmisaka #define get_srv_buffer() \
37*437bfbebSnyanmisaka ({ \
38*437bfbebSnyanmisaka MppBufferService *__tmp; \
39*437bfbebSnyanmisaka if (srv_buffer) \
40*437bfbebSnyanmisaka __tmp = srv_buffer; \
41*437bfbebSnyanmisaka else { \
42*437bfbebSnyanmisaka switch (srv_status) { \
43*437bfbebSnyanmisaka case MPP_BUF_SRV_UNINITED : { \
44*437bfbebSnyanmisaka mpp_buffer_service_init(); \
45*437bfbebSnyanmisaka __tmp = srv_buffer; \
46*437bfbebSnyanmisaka } break; \
47*437bfbebSnyanmisaka case MPP_BUF_SRV_FINALIZED : { \
48*437bfbebSnyanmisaka /* if called after buf srv deinited return NULL without error log */ \
49*437bfbebSnyanmisaka __tmp = NULL; \
50*437bfbebSnyanmisaka } break; \
51*437bfbebSnyanmisaka default : { \
52*437bfbebSnyanmisaka mpp_err("mpp buffer srv not init status %d at %s\n", __FUNCTION__); \
53*437bfbebSnyanmisaka __tmp = NULL; \
54*437bfbebSnyanmisaka } break; \
55*437bfbebSnyanmisaka } \
56*437bfbebSnyanmisaka } \
57*437bfbebSnyanmisaka __tmp; \
58*437bfbebSnyanmisaka })
59*437bfbebSnyanmisaka
60*437bfbebSnyanmisaka static void mpp_buffer_service_init();
61*437bfbebSnyanmisaka
62*437bfbebSnyanmisaka typedef MPP_RET (*BufferOp)(MppAllocator allocator, MppBufferInfo *data);
63*437bfbebSnyanmisaka
64*437bfbebSnyanmisaka typedef struct MppBufferService_t {
65*437bfbebSnyanmisaka rk_u32 group_id;
66*437bfbebSnyanmisaka rk_u32 group_count;
67*437bfbebSnyanmisaka rk_u32 finalizing;
68*437bfbebSnyanmisaka
69*437bfbebSnyanmisaka rk_u32 total_size;
70*437bfbebSnyanmisaka rk_u32 total_max;
71*437bfbebSnyanmisaka
72*437bfbebSnyanmisaka MppMutex lock;
73*437bfbebSnyanmisaka // misc group for internal / externl buffer with different type
74*437bfbebSnyanmisaka rk_u32 misc[MPP_BUFFER_MODE_BUTT][MPP_BUFFER_TYPE_BUTT][MPP_ALLOCATOR_WITH_FLAG_NUM];
75*437bfbebSnyanmisaka rk_u32 misc_count;
76*437bfbebSnyanmisaka /* preset allocator apis */
77*437bfbebSnyanmisaka MppAllocator allocator[MPP_BUFFER_TYPE_BUTT][MPP_ALLOCATOR_WITH_FLAG_NUM];
78*437bfbebSnyanmisaka MppAllocatorApi *allocator_api[MPP_BUFFER_TYPE_BUTT];
79*437bfbebSnyanmisaka
80*437bfbebSnyanmisaka struct list_head list_group;
81*437bfbebSnyanmisaka DECLARE_HASHTABLE(hash_group, MAX_GROUP_BIT);
82*437bfbebSnyanmisaka
83*437bfbebSnyanmisaka // list for used buffer which do not have group
84*437bfbebSnyanmisaka struct list_head list_orphan;
85*437bfbebSnyanmisaka } MppBufferService;
86*437bfbebSnyanmisaka
87*437bfbebSnyanmisaka static const char *mode2str[MPP_BUFFER_MODE_BUTT] = {
88*437bfbebSnyanmisaka "internal",
89*437bfbebSnyanmisaka "external",
90*437bfbebSnyanmisaka };
91*437bfbebSnyanmisaka
92*437bfbebSnyanmisaka static const char *type2str[MPP_BUFFER_TYPE_BUTT] = {
93*437bfbebSnyanmisaka "normal",
94*437bfbebSnyanmisaka "ion",
95*437bfbebSnyanmisaka "dma-buf",
96*437bfbebSnyanmisaka "drm",
97*437bfbebSnyanmisaka };
98*437bfbebSnyanmisaka static const char *ops2str[BUF_OPS_BUTT] = {
99*437bfbebSnyanmisaka "grp create ",
100*437bfbebSnyanmisaka "grp release",
101*437bfbebSnyanmisaka "grp reset",
102*437bfbebSnyanmisaka "grp orphan",
103*437bfbebSnyanmisaka "grp destroy",
104*437bfbebSnyanmisaka
105*437bfbebSnyanmisaka "buf commit ",
106*437bfbebSnyanmisaka "buf create ",
107*437bfbebSnyanmisaka "buf mmap ",
108*437bfbebSnyanmisaka "buf ref inc",
109*437bfbebSnyanmisaka "buf ref dec",
110*437bfbebSnyanmisaka "buf discard",
111*437bfbebSnyanmisaka "buf destroy",
112*437bfbebSnyanmisaka };
113*437bfbebSnyanmisaka
114*437bfbebSnyanmisaka static MppMemPool pool_buf = NULL;
115*437bfbebSnyanmisaka static MppMemPool pool_buf_grp = NULL;
116*437bfbebSnyanmisaka static MppMemPool pool_buf_map_node = NULL;
117*437bfbebSnyanmisaka static MppBufferService *srv_buffer = NULL;
118*437bfbebSnyanmisaka static MppBufSrvStatus srv_status = MPP_BUF_SRV_UNINITED;
119*437bfbebSnyanmisaka rk_u32 mpp_buffer_debug = 0;
120*437bfbebSnyanmisaka
121*437bfbebSnyanmisaka static MppBufferGroupImpl *service_get_group(const char *tag, const char *caller,
122*437bfbebSnyanmisaka MppBufferMode mode, MppBufferType type,
123*437bfbebSnyanmisaka rk_u32 is_misc);
124*437bfbebSnyanmisaka
125*437bfbebSnyanmisaka static void service_put_group(MppBufferService *srv, MppBufferGroupImpl *p, const char *caller);
126*437bfbebSnyanmisaka static void service_dump(MppBufferService *srv, const char *info);
127*437bfbebSnyanmisaka
get_group_by_id(MppBufferService * srv,rk_u32 id)128*437bfbebSnyanmisaka static MppBufferGroupImpl *get_group_by_id(MppBufferService *srv, rk_u32 id)
129*437bfbebSnyanmisaka {
130*437bfbebSnyanmisaka MppBufferGroupImpl *impl = NULL;
131*437bfbebSnyanmisaka
132*437bfbebSnyanmisaka hash_for_each_possible(srv->hash_group, impl, hlist, id) {
133*437bfbebSnyanmisaka if (impl->group_id == id)
134*437bfbebSnyanmisaka break;
135*437bfbebSnyanmisaka }
136*437bfbebSnyanmisaka
137*437bfbebSnyanmisaka return impl;
138*437bfbebSnyanmisaka }
139*437bfbebSnyanmisaka
buf_logs_init(rk_u32 max_count)140*437bfbebSnyanmisaka static MppBufLogs *buf_logs_init(rk_u32 max_count)
141*437bfbebSnyanmisaka {
142*437bfbebSnyanmisaka MppBufLogs *logs = NULL;
143*437bfbebSnyanmisaka
144*437bfbebSnyanmisaka if (!max_count)
145*437bfbebSnyanmisaka return NULL;
146*437bfbebSnyanmisaka
147*437bfbebSnyanmisaka logs = mpp_malloc_size(MppBufLogs, sizeof(MppBufLogs) + max_count * sizeof(MppBufLog));
148*437bfbebSnyanmisaka if (!logs) {
149*437bfbebSnyanmisaka mpp_err_f("failed to create %d buf logs\n", max_count);
150*437bfbebSnyanmisaka return NULL;
151*437bfbebSnyanmisaka }
152*437bfbebSnyanmisaka
153*437bfbebSnyanmisaka {
154*437bfbebSnyanmisaka pthread_mutexattr_t attr;
155*437bfbebSnyanmisaka
156*437bfbebSnyanmisaka pthread_mutexattr_init(&attr);
157*437bfbebSnyanmisaka pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
158*437bfbebSnyanmisaka pthread_mutex_init(&logs->lock, &attr);
159*437bfbebSnyanmisaka pthread_mutexattr_destroy(&attr);
160*437bfbebSnyanmisaka }
161*437bfbebSnyanmisaka
162*437bfbebSnyanmisaka logs->max_count = max_count;
163*437bfbebSnyanmisaka logs->log_count = 0;
164*437bfbebSnyanmisaka logs->log_write = 0;
165*437bfbebSnyanmisaka logs->log_read = 0;
166*437bfbebSnyanmisaka logs->logs = (MppBufLog *)(logs + 1);
167*437bfbebSnyanmisaka
168*437bfbebSnyanmisaka return logs;
169*437bfbebSnyanmisaka }
170*437bfbebSnyanmisaka
buf_logs_deinit(MppBufLogs * logs)171*437bfbebSnyanmisaka static void buf_logs_deinit(MppBufLogs *logs)
172*437bfbebSnyanmisaka {
173*437bfbebSnyanmisaka pthread_mutex_destroy(&logs->lock);
174*437bfbebSnyanmisaka MPP_FREE(logs);
175*437bfbebSnyanmisaka }
176*437bfbebSnyanmisaka
buf_logs_write(MppBufLogs * logs,rk_u32 group_id,rk_s32 buffer_id,MppBufOps ops,rk_s32 ref_count,const char * caller)177*437bfbebSnyanmisaka static void buf_logs_write(MppBufLogs *logs, rk_u32 group_id, rk_s32 buffer_id,
178*437bfbebSnyanmisaka MppBufOps ops, rk_s32 ref_count, const char *caller)
179*437bfbebSnyanmisaka {
180*437bfbebSnyanmisaka MppBufLog *log = NULL;
181*437bfbebSnyanmisaka
182*437bfbebSnyanmisaka pthread_mutex_lock(&logs->lock);
183*437bfbebSnyanmisaka
184*437bfbebSnyanmisaka log = &logs->logs[logs->log_write];
185*437bfbebSnyanmisaka log->group_id = group_id;
186*437bfbebSnyanmisaka log->buffer_id = buffer_id;
187*437bfbebSnyanmisaka log->ops = ops;
188*437bfbebSnyanmisaka log->ref_count = ref_count;
189*437bfbebSnyanmisaka log->caller = caller;
190*437bfbebSnyanmisaka
191*437bfbebSnyanmisaka logs->log_write++;
192*437bfbebSnyanmisaka if (logs->log_write >= logs->max_count)
193*437bfbebSnyanmisaka logs->log_write = 0;
194*437bfbebSnyanmisaka
195*437bfbebSnyanmisaka if (logs->log_count < logs->max_count)
196*437bfbebSnyanmisaka logs->log_count++;
197*437bfbebSnyanmisaka else {
198*437bfbebSnyanmisaka logs->log_read++;
199*437bfbebSnyanmisaka if (logs->log_read >= logs->max_count)
200*437bfbebSnyanmisaka logs->log_read = 0;
201*437bfbebSnyanmisaka }
202*437bfbebSnyanmisaka
203*437bfbebSnyanmisaka pthread_mutex_unlock(&logs->lock);
204*437bfbebSnyanmisaka }
205*437bfbebSnyanmisaka
buf_logs_dump(MppBufLogs * logs)206*437bfbebSnyanmisaka static void buf_logs_dump(MppBufLogs *logs)
207*437bfbebSnyanmisaka {
208*437bfbebSnyanmisaka while (logs->log_count) {
209*437bfbebSnyanmisaka MppBufLog *log = &logs->logs[logs->log_read];
210*437bfbebSnyanmisaka
211*437bfbebSnyanmisaka if (log->buffer_id >= 0)
212*437bfbebSnyanmisaka mpp_log("group %3d buffer %4d ops %s ref_count %d caller %s\n",
213*437bfbebSnyanmisaka log->group_id, log->buffer_id,
214*437bfbebSnyanmisaka ops2str[log->ops], log->ref_count, log->caller);
215*437bfbebSnyanmisaka else
216*437bfbebSnyanmisaka mpp_log("group %3d ops %s\n", log->group_id, ops2str[log->ops]);
217*437bfbebSnyanmisaka
218*437bfbebSnyanmisaka logs->log_read++;
219*437bfbebSnyanmisaka if (logs->log_read >= logs->max_count)
220*437bfbebSnyanmisaka logs->log_read = 0;
221*437bfbebSnyanmisaka logs->log_count--;
222*437bfbebSnyanmisaka }
223*437bfbebSnyanmisaka mpp_assert(logs->log_read == logs->log_write);
224*437bfbebSnyanmisaka }
225*437bfbebSnyanmisaka
buf_add_log(MppBufferImpl * buffer,MppBufOps ops,const char * caller)226*437bfbebSnyanmisaka static void buf_add_log(MppBufferImpl *buffer, MppBufOps ops, const char* caller)
227*437bfbebSnyanmisaka {
228*437bfbebSnyanmisaka if (buffer->log_runtime_en) {
229*437bfbebSnyanmisaka mpp_log("group %3d buffer %4d fd %3d ops %s ref_count %d caller %s\n",
230*437bfbebSnyanmisaka buffer->group_id, buffer->buffer_id, buffer->info.fd,
231*437bfbebSnyanmisaka ops2str[ops], buffer->ref_count, caller);
232*437bfbebSnyanmisaka }
233*437bfbebSnyanmisaka if (buffer->logs)
234*437bfbebSnyanmisaka buf_logs_write(buffer->logs, buffer->group_id, buffer->buffer_id,
235*437bfbebSnyanmisaka ops, buffer->ref_count, caller);
236*437bfbebSnyanmisaka }
237*437bfbebSnyanmisaka
buf_grp_add_log(MppBufferGroupImpl * group,MppBufOps ops,const char * caller)238*437bfbebSnyanmisaka static void buf_grp_add_log(MppBufferGroupImpl *group, MppBufOps ops, const char* caller)
239*437bfbebSnyanmisaka {
240*437bfbebSnyanmisaka if (group->log_runtime_en) {
241*437bfbebSnyanmisaka mpp_log("group %3d mode %d type %d ops %s\n", group->group_id,
242*437bfbebSnyanmisaka group->mode, group->type, ops2str[ops]);
243*437bfbebSnyanmisaka }
244*437bfbebSnyanmisaka if (group->logs)
245*437bfbebSnyanmisaka buf_logs_write(group->logs, group->group_id, -1, ops, 0, caller);
246*437bfbebSnyanmisaka }
247*437bfbebSnyanmisaka
dump_buffer_info(MppBufferImpl * buffer)248*437bfbebSnyanmisaka static void dump_buffer_info(MppBufferImpl *buffer)
249*437bfbebSnyanmisaka {
250*437bfbebSnyanmisaka mpp_log("buffer %p fd %4d size %10d ref_count %3d discard %d caller %s\n",
251*437bfbebSnyanmisaka buffer, buffer->info.fd, buffer->info.size,
252*437bfbebSnyanmisaka buffer->ref_count, buffer->discard, buffer->caller);
253*437bfbebSnyanmisaka }
254*437bfbebSnyanmisaka
mpp_buffer_group_dump(MppBufferGroupImpl * group,const char * caller)255*437bfbebSnyanmisaka void mpp_buffer_group_dump(MppBufferGroupImpl *group, const char *caller)
256*437bfbebSnyanmisaka {
257*437bfbebSnyanmisaka MppBufferImpl *pos, *n;
258*437bfbebSnyanmisaka
259*437bfbebSnyanmisaka mpp_log("\ndumping buffer group %p id %d from %s\n", group,
260*437bfbebSnyanmisaka group->group_id, caller);
261*437bfbebSnyanmisaka mpp_log("mode %s\n", mode2str[group->mode]);
262*437bfbebSnyanmisaka mpp_log("type %s\n", type2str[group->type]);
263*437bfbebSnyanmisaka mpp_log("limit size %d count %d\n", group->limit_size, group->limit_count);
264*437bfbebSnyanmisaka
265*437bfbebSnyanmisaka mpp_log("used buffer count %d\n", group->count_used);
266*437bfbebSnyanmisaka
267*437bfbebSnyanmisaka list_for_each_entry_safe(pos, n, &group->list_used, MppBufferImpl, list_status) {
268*437bfbebSnyanmisaka dump_buffer_info(pos);
269*437bfbebSnyanmisaka }
270*437bfbebSnyanmisaka
271*437bfbebSnyanmisaka mpp_log("unused buffer count %d\n", group->count_unused);
272*437bfbebSnyanmisaka list_for_each_entry_safe(pos, n, &group->list_unused, MppBufferImpl, list_status) {
273*437bfbebSnyanmisaka dump_buffer_info(pos);
274*437bfbebSnyanmisaka }
275*437bfbebSnyanmisaka
276*437bfbebSnyanmisaka if (group->logs)
277*437bfbebSnyanmisaka buf_logs_dump(group->logs);
278*437bfbebSnyanmisaka }
279*437bfbebSnyanmisaka
clear_buffer_info(MppBufferInfo * info)280*437bfbebSnyanmisaka static void clear_buffer_info(MppBufferInfo *info)
281*437bfbebSnyanmisaka {
282*437bfbebSnyanmisaka info->fd = -1;
283*437bfbebSnyanmisaka info->ptr = NULL;
284*437bfbebSnyanmisaka info->hnd = NULL;
285*437bfbebSnyanmisaka info->size = 0;
286*437bfbebSnyanmisaka info->index = -1;
287*437bfbebSnyanmisaka info->type = MPP_BUFFER_TYPE_BUTT;
288*437bfbebSnyanmisaka }
289*437bfbebSnyanmisaka
service_put_buffer(MppBufferService * srv,MppBufferGroupImpl * group,MppBufferImpl * buffer,rk_u32 reuse,const char * caller)290*437bfbebSnyanmisaka static void service_put_buffer(MppBufferService *srv, MppBufferGroupImpl *group,
291*437bfbebSnyanmisaka MppBufferImpl *buffer, rk_u32 reuse, const char *caller)
292*437bfbebSnyanmisaka {
293*437bfbebSnyanmisaka struct list_head list_maps;
294*437bfbebSnyanmisaka MppDevBufMapNode *pos, *n;
295*437bfbebSnyanmisaka MppBufferInfo info;
296*437bfbebSnyanmisaka
297*437bfbebSnyanmisaka mpp_assert(group);
298*437bfbebSnyanmisaka
299*437bfbebSnyanmisaka pthread_mutex_lock(&buffer->lock);
300*437bfbebSnyanmisaka
301*437bfbebSnyanmisaka if (!srv && !srv->finalizing) {
302*437bfbebSnyanmisaka mpp_assert(buffer->ref_count == 0);
303*437bfbebSnyanmisaka if (buffer->ref_count > 0) {
304*437bfbebSnyanmisaka pthread_mutex_unlock(&buffer->lock);
305*437bfbebSnyanmisaka return;
306*437bfbebSnyanmisaka }
307*437bfbebSnyanmisaka }
308*437bfbebSnyanmisaka
309*437bfbebSnyanmisaka list_del_init(&buffer->list_status);
310*437bfbebSnyanmisaka
311*437bfbebSnyanmisaka if (reuse) {
312*437bfbebSnyanmisaka if (buffer->used && group) {
313*437bfbebSnyanmisaka group->count_used--;
314*437bfbebSnyanmisaka list_add_tail(&buffer->list_status, &group->list_unused);
315*437bfbebSnyanmisaka group->count_unused++;
316*437bfbebSnyanmisaka } else {
317*437bfbebSnyanmisaka mpp_err_f("can not reuse unused buffer %d at group %p:%d\n",
318*437bfbebSnyanmisaka buffer->buffer_id, group, buffer->group_id);
319*437bfbebSnyanmisaka }
320*437bfbebSnyanmisaka buffer->used = 0;
321*437bfbebSnyanmisaka
322*437bfbebSnyanmisaka pthread_mutex_unlock(&buffer->lock);
323*437bfbebSnyanmisaka return;
324*437bfbebSnyanmisaka }
325*437bfbebSnyanmisaka
326*437bfbebSnyanmisaka /* remove all map from buffer */
327*437bfbebSnyanmisaka INIT_LIST_HEAD(&list_maps);
328*437bfbebSnyanmisaka list_for_each_entry_safe(pos, n, &buffer->list_maps, MppDevBufMapNode, list_buf) {
329*437bfbebSnyanmisaka list_move_tail(&pos->list_buf, &list_maps);
330*437bfbebSnyanmisaka pos->iova = (rk_u32)(-1);
331*437bfbebSnyanmisaka }
332*437bfbebSnyanmisaka mpp_assert(list_empty(&buffer->list_maps));
333*437bfbebSnyanmisaka info = buffer->info;
334*437bfbebSnyanmisaka if (group) {
335*437bfbebSnyanmisaka rk_u32 destroy = 0;
336*437bfbebSnyanmisaka rk_u32 size = buffer->info.size;
337*437bfbebSnyanmisaka
338*437bfbebSnyanmisaka if (buffer->used)
339*437bfbebSnyanmisaka group->count_used--;
340*437bfbebSnyanmisaka else
341*437bfbebSnyanmisaka group->count_unused--;
342*437bfbebSnyanmisaka
343*437bfbebSnyanmisaka group->usage -= size;
344*437bfbebSnyanmisaka group->buffer_count--;
345*437bfbebSnyanmisaka
346*437bfbebSnyanmisaka /* reduce total buffer size record */
347*437bfbebSnyanmisaka if (group->mode == MPP_BUFFER_INTERNAL && srv)
348*437bfbebSnyanmisaka MPP_FETCH_SUB(&srv->total_size, size);
349*437bfbebSnyanmisaka
350*437bfbebSnyanmisaka buf_add_log(buffer, BUF_DESTROY, caller);
351*437bfbebSnyanmisaka
352*437bfbebSnyanmisaka if (group->is_orphan && !group->usage && !group->is_finalizing)
353*437bfbebSnyanmisaka destroy = 1;
354*437bfbebSnyanmisaka
355*437bfbebSnyanmisaka if (destroy)
356*437bfbebSnyanmisaka service_put_group(srv, group, caller);
357*437bfbebSnyanmisaka } else {
358*437bfbebSnyanmisaka mpp_assert(srv_status);
359*437bfbebSnyanmisaka }
360*437bfbebSnyanmisaka clear_buffer_info(&buffer->info);
361*437bfbebSnyanmisaka
362*437bfbebSnyanmisaka pthread_mutex_unlock(&buffer->lock);
363*437bfbebSnyanmisaka
364*437bfbebSnyanmisaka list_for_each_entry_safe(pos, n, &list_maps, MppDevBufMapNode, list_buf) {
365*437bfbebSnyanmisaka MppDev dev = pos->dev;
366*437bfbebSnyanmisaka
367*437bfbebSnyanmisaka mpp_assert(dev);
368*437bfbebSnyanmisaka mpp_dev_ioctl(dev, MPP_DEV_LOCK_MAP, NULL);
369*437bfbebSnyanmisaka /* remove buffer from group */
370*437bfbebSnyanmisaka mpp_dev_ioctl(dev, MPP_DEV_DETACH_FD, pos);
371*437bfbebSnyanmisaka mpp_dev_ioctl(dev, MPP_DEV_UNLOCK_MAP, NULL);
372*437bfbebSnyanmisaka mpp_mem_pool_put(pool_buf_map_node, pos, caller);
373*437bfbebSnyanmisaka }
374*437bfbebSnyanmisaka
375*437bfbebSnyanmisaka /* release buffer here */
376*437bfbebSnyanmisaka {
377*437bfbebSnyanmisaka BufferOp func = (buffer->mode == MPP_BUFFER_INTERNAL) ?
378*437bfbebSnyanmisaka (buffer->alloc_api->free) :
379*437bfbebSnyanmisaka (buffer->alloc_api->release);
380*437bfbebSnyanmisaka
381*437bfbebSnyanmisaka func(buffer->allocator, &info);
382*437bfbebSnyanmisaka }
383*437bfbebSnyanmisaka
384*437bfbebSnyanmisaka mpp_mem_pool_put(pool_buf, buffer, caller);
385*437bfbebSnyanmisaka }
386*437bfbebSnyanmisaka
inc_buffer_ref(MppBufferImpl * buffer,const char * caller)387*437bfbebSnyanmisaka static MPP_RET inc_buffer_ref(MppBufferImpl *buffer, const char *caller)
388*437bfbebSnyanmisaka {
389*437bfbebSnyanmisaka MPP_RET ret = MPP_OK;
390*437bfbebSnyanmisaka
391*437bfbebSnyanmisaka pthread_mutex_lock(&buffer->lock);
392*437bfbebSnyanmisaka buffer->ref_count++;
393*437bfbebSnyanmisaka buf_add_log(buffer, BUF_REF_INC, caller);
394*437bfbebSnyanmisaka if (!buffer->used) {
395*437bfbebSnyanmisaka MppBufferGroupImpl *group = NULL;
396*437bfbebSnyanmisaka MppBufferService *srv = get_srv_buffer();
397*437bfbebSnyanmisaka
398*437bfbebSnyanmisaka if (srv) {
399*437bfbebSnyanmisaka mpp_mutex_lock(&srv->lock);
400*437bfbebSnyanmisaka group = SEARCH_GROUP_BY_ID(srv, buffer->group_id);
401*437bfbebSnyanmisaka mpp_mutex_unlock(&srv->lock);
402*437bfbebSnyanmisaka }
403*437bfbebSnyanmisaka // NOTE: when increasing ref_count the unused buffer must be under certain group
404*437bfbebSnyanmisaka mpp_assert(group);
405*437bfbebSnyanmisaka buffer->used = 1;
406*437bfbebSnyanmisaka if (group) {
407*437bfbebSnyanmisaka pthread_mutex_lock(&group->buf_lock);
408*437bfbebSnyanmisaka list_del_init(&buffer->list_status);
409*437bfbebSnyanmisaka list_add_tail(&buffer->list_status, &group->list_used);
410*437bfbebSnyanmisaka group->count_used++;
411*437bfbebSnyanmisaka group->count_unused--;
412*437bfbebSnyanmisaka pthread_mutex_unlock(&group->buf_lock);
413*437bfbebSnyanmisaka } else {
414*437bfbebSnyanmisaka mpp_err_f("unused buffer without group\n");
415*437bfbebSnyanmisaka ret = MPP_NOK;
416*437bfbebSnyanmisaka }
417*437bfbebSnyanmisaka }
418*437bfbebSnyanmisaka pthread_mutex_unlock(&buffer->lock);
419*437bfbebSnyanmisaka return ret;
420*437bfbebSnyanmisaka }
421*437bfbebSnyanmisaka
mpp_buffer_create(const char * tag,const char * caller,MppBufferGroupImpl * group,MppBufferInfo * info,MppBufferImpl ** buffer)422*437bfbebSnyanmisaka MPP_RET mpp_buffer_create(const char *tag, const char *caller,
423*437bfbebSnyanmisaka MppBufferGroupImpl *group, MppBufferInfo *info,
424*437bfbebSnyanmisaka MppBufferImpl **buffer)
425*437bfbebSnyanmisaka {
426*437bfbebSnyanmisaka MPP_BUF_FUNCTION_ENTER();
427*437bfbebSnyanmisaka
428*437bfbebSnyanmisaka MPP_RET ret = MPP_OK;
429*437bfbebSnyanmisaka BufferOp func = NULL;
430*437bfbebSnyanmisaka MppBufferImpl *p = NULL;
431*437bfbebSnyanmisaka
432*437bfbebSnyanmisaka if (!group) {
433*437bfbebSnyanmisaka mpp_err_f("can not create buffer without group\n");
434*437bfbebSnyanmisaka ret = MPP_NOK;
435*437bfbebSnyanmisaka goto RET;
436*437bfbebSnyanmisaka }
437*437bfbebSnyanmisaka
438*437bfbebSnyanmisaka if (group->limit_count && group->buffer_count >= group->limit_count) {
439*437bfbebSnyanmisaka if (group->log_runtime_en)
440*437bfbebSnyanmisaka mpp_log_f("group %d reach count limit %d\n", group->group_id, group->limit_count);
441*437bfbebSnyanmisaka ret = MPP_NOK;
442*437bfbebSnyanmisaka goto RET;
443*437bfbebSnyanmisaka }
444*437bfbebSnyanmisaka
445*437bfbebSnyanmisaka if (group->limit_size && info->size > group->limit_size) {
446*437bfbebSnyanmisaka mpp_err_f("required size %d reach group size limit %d\n", info->size, group->limit_size);
447*437bfbebSnyanmisaka ret = MPP_NOK;
448*437bfbebSnyanmisaka goto RET;
449*437bfbebSnyanmisaka }
450*437bfbebSnyanmisaka
451*437bfbebSnyanmisaka p = (MppBufferImpl *)mpp_mem_pool_get(pool_buf, caller);
452*437bfbebSnyanmisaka if (!p) {
453*437bfbebSnyanmisaka mpp_err_f("failed to allocate context\n");
454*437bfbebSnyanmisaka ret = MPP_ERR_MALLOC;
455*437bfbebSnyanmisaka goto RET;
456*437bfbebSnyanmisaka }
457*437bfbebSnyanmisaka
458*437bfbebSnyanmisaka func = (group->mode == MPP_BUFFER_INTERNAL) ?
459*437bfbebSnyanmisaka (group->alloc_api->alloc) : (group->alloc_api->import);
460*437bfbebSnyanmisaka ret = func(group->allocator, info);
461*437bfbebSnyanmisaka if (ret) {
462*437bfbebSnyanmisaka mpp_err_f("failed to create buffer with size %d\n", info->size);
463*437bfbebSnyanmisaka mpp_mem_pool_put(pool_buf, p, caller);
464*437bfbebSnyanmisaka ret = MPP_ERR_MALLOC;
465*437bfbebSnyanmisaka goto RET;
466*437bfbebSnyanmisaka }
467*437bfbebSnyanmisaka
468*437bfbebSnyanmisaka if (!tag)
469*437bfbebSnyanmisaka tag = group->tag;
470*437bfbebSnyanmisaka
471*437bfbebSnyanmisaka snprintf(p->tag, sizeof(p->tag), "%s", tag);
472*437bfbebSnyanmisaka p->caller = caller;
473*437bfbebSnyanmisaka pthread_mutexattr_t attr;
474*437bfbebSnyanmisaka pthread_mutexattr_init(&attr);
475*437bfbebSnyanmisaka pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
476*437bfbebSnyanmisaka pthread_mutex_init(&p->lock, &attr);
477*437bfbebSnyanmisaka pthread_mutexattr_destroy(&attr);
478*437bfbebSnyanmisaka p->allocator = group->allocator;
479*437bfbebSnyanmisaka p->alloc_api = group->alloc_api;
480*437bfbebSnyanmisaka p->log_runtime_en = group->log_runtime_en;
481*437bfbebSnyanmisaka p->log_history_en = group->log_history_en;
482*437bfbebSnyanmisaka p->group_id = group->group_id;
483*437bfbebSnyanmisaka p->mode = group->mode;
484*437bfbebSnyanmisaka p->type = group->type;
485*437bfbebSnyanmisaka p->uncached = (group->flags & MPP_ALLOC_FLAG_CACHABLE) ? 0 : 1;
486*437bfbebSnyanmisaka p->logs = group->logs;
487*437bfbebSnyanmisaka p->info = *info;
488*437bfbebSnyanmisaka
489*437bfbebSnyanmisaka pthread_mutex_lock(&group->buf_lock);
490*437bfbebSnyanmisaka p->buffer_id = group->buffer_id++;
491*437bfbebSnyanmisaka INIT_LIST_HEAD(&p->list_status);
492*437bfbebSnyanmisaka INIT_LIST_HEAD(&p->list_maps);
493*437bfbebSnyanmisaka
494*437bfbebSnyanmisaka if (buffer) {
495*437bfbebSnyanmisaka p->ref_count++;
496*437bfbebSnyanmisaka p->used = 1;
497*437bfbebSnyanmisaka list_add_tail(&p->list_status, &group->list_used);
498*437bfbebSnyanmisaka group->count_used++;
499*437bfbebSnyanmisaka *buffer = p;
500*437bfbebSnyanmisaka } else {
501*437bfbebSnyanmisaka list_add_tail(&p->list_status, &group->list_unused);
502*437bfbebSnyanmisaka group->count_unused++;
503*437bfbebSnyanmisaka }
504*437bfbebSnyanmisaka
505*437bfbebSnyanmisaka group->usage += info->size;
506*437bfbebSnyanmisaka group->buffer_count++;
507*437bfbebSnyanmisaka pthread_mutex_unlock(&group->buf_lock);
508*437bfbebSnyanmisaka
509*437bfbebSnyanmisaka buf_add_log(p, (group->mode == MPP_BUFFER_INTERNAL) ? (BUF_CREATE) : (BUF_COMMIT), caller);
510*437bfbebSnyanmisaka
511*437bfbebSnyanmisaka if (group->mode == MPP_BUFFER_INTERNAL) {
512*437bfbebSnyanmisaka MppBufferService *srv = get_srv_buffer();
513*437bfbebSnyanmisaka
514*437bfbebSnyanmisaka if (srv) {
515*437bfbebSnyanmisaka rk_u32 total = MPP_ADD_FETCH(&srv->total_size, info->size);
516*437bfbebSnyanmisaka bool cas_ret;
517*437bfbebSnyanmisaka
518*437bfbebSnyanmisaka do {
519*437bfbebSnyanmisaka rk_u32 old_max = srv->total_max;
520*437bfbebSnyanmisaka rk_u32 new_max = MPP_MAX(total, old_max);
521*437bfbebSnyanmisaka
522*437bfbebSnyanmisaka cas_ret = MPP_BOOL_CAS(&srv->total_max, old_max, new_max);
523*437bfbebSnyanmisaka } while (!cas_ret);
524*437bfbebSnyanmisaka }
525*437bfbebSnyanmisaka }
526*437bfbebSnyanmisaka
527*437bfbebSnyanmisaka if (group->callback)
528*437bfbebSnyanmisaka group->callback(group->arg, group);
529*437bfbebSnyanmisaka RET:
530*437bfbebSnyanmisaka MPP_BUF_FUNCTION_LEAVE();
531*437bfbebSnyanmisaka return ret;
532*437bfbebSnyanmisaka }
533*437bfbebSnyanmisaka
mpp_buffer_mmap(MppBufferImpl * buffer,const char * caller)534*437bfbebSnyanmisaka MPP_RET mpp_buffer_mmap(MppBufferImpl *buffer, const char* caller)
535*437bfbebSnyanmisaka {
536*437bfbebSnyanmisaka MPP_BUF_FUNCTION_ENTER();
537*437bfbebSnyanmisaka
538*437bfbebSnyanmisaka MPP_RET ret = buffer->alloc_api->mmap(buffer->allocator, &buffer->info);
539*437bfbebSnyanmisaka if (ret)
540*437bfbebSnyanmisaka mpp_err_f("buffer %d group %d fd %d map failed caller %s\n",
541*437bfbebSnyanmisaka buffer->buffer_id, buffer->group_id, buffer->info.fd, caller);
542*437bfbebSnyanmisaka
543*437bfbebSnyanmisaka buf_add_log(buffer, BUF_MMAP, caller);
544*437bfbebSnyanmisaka
545*437bfbebSnyanmisaka MPP_BUF_FUNCTION_LEAVE();
546*437bfbebSnyanmisaka return ret;
547*437bfbebSnyanmisaka }
548*437bfbebSnyanmisaka
mpp_buffer_ref_inc(MppBufferImpl * buffer,const char * caller)549*437bfbebSnyanmisaka MPP_RET mpp_buffer_ref_inc(MppBufferImpl *buffer, const char* caller)
550*437bfbebSnyanmisaka {
551*437bfbebSnyanmisaka MPP_BUF_FUNCTION_ENTER();
552*437bfbebSnyanmisaka
553*437bfbebSnyanmisaka MPP_RET ret = inc_buffer_ref(buffer, caller);
554*437bfbebSnyanmisaka
555*437bfbebSnyanmisaka MPP_BUF_FUNCTION_LEAVE();
556*437bfbebSnyanmisaka return ret;
557*437bfbebSnyanmisaka }
558*437bfbebSnyanmisaka
559*437bfbebSnyanmisaka
mpp_buffer_ref_dec(MppBufferImpl * buffer,const char * caller)560*437bfbebSnyanmisaka MPP_RET mpp_buffer_ref_dec(MppBufferImpl *buffer, const char* caller)
561*437bfbebSnyanmisaka {
562*437bfbebSnyanmisaka MPP_RET ret = MPP_OK;
563*437bfbebSnyanmisaka rk_u32 release = 0;
564*437bfbebSnyanmisaka
565*437bfbebSnyanmisaka MPP_BUF_FUNCTION_ENTER();
566*437bfbebSnyanmisaka
567*437bfbebSnyanmisaka pthread_mutex_lock(&buffer->lock);
568*437bfbebSnyanmisaka
569*437bfbebSnyanmisaka if (buffer->ref_count <= 0) {
570*437bfbebSnyanmisaka buf_add_log(buffer, BUF_REF_DEC, caller);
571*437bfbebSnyanmisaka mpp_err_f("buffer from %s found non-positive ref_count %d caller %s\n",
572*437bfbebSnyanmisaka buffer->caller, buffer->ref_count, caller);
573*437bfbebSnyanmisaka mpp_abort();
574*437bfbebSnyanmisaka ret = MPP_NOK;
575*437bfbebSnyanmisaka pthread_mutex_unlock(&buffer->lock);
576*437bfbebSnyanmisaka goto done;
577*437bfbebSnyanmisaka }
578*437bfbebSnyanmisaka
579*437bfbebSnyanmisaka buffer->ref_count--;
580*437bfbebSnyanmisaka if (buffer->ref_count == 0)
581*437bfbebSnyanmisaka release = 1;
582*437bfbebSnyanmisaka buf_add_log(buffer, BUF_REF_DEC, caller);
583*437bfbebSnyanmisaka
584*437bfbebSnyanmisaka pthread_mutex_unlock(&buffer->lock);
585*437bfbebSnyanmisaka
586*437bfbebSnyanmisaka if (release) {
587*437bfbebSnyanmisaka MppBufferGroupImpl *group = NULL;
588*437bfbebSnyanmisaka MppBufferService *srv = get_srv_buffer();
589*437bfbebSnyanmisaka
590*437bfbebSnyanmisaka if (srv) {
591*437bfbebSnyanmisaka mpp_mutex_lock(&srv->lock);
592*437bfbebSnyanmisaka group = SEARCH_GROUP_BY_ID(srv, buffer->group_id);
593*437bfbebSnyanmisaka mpp_mutex_unlock(&srv->lock);
594*437bfbebSnyanmisaka }
595*437bfbebSnyanmisaka
596*437bfbebSnyanmisaka mpp_assert(group);
597*437bfbebSnyanmisaka if (group) {
598*437bfbebSnyanmisaka rk_u32 reuse = 0;
599*437bfbebSnyanmisaka
600*437bfbebSnyanmisaka pthread_mutex_lock(&group->buf_lock);
601*437bfbebSnyanmisaka
602*437bfbebSnyanmisaka reuse = (!group->is_misc && !buffer->discard);
603*437bfbebSnyanmisaka service_put_buffer(srv, group, buffer, reuse, caller);
604*437bfbebSnyanmisaka
605*437bfbebSnyanmisaka if (group->callback)
606*437bfbebSnyanmisaka group->callback(group->arg, group);
607*437bfbebSnyanmisaka
608*437bfbebSnyanmisaka pthread_mutex_unlock(&group->buf_lock);
609*437bfbebSnyanmisaka }
610*437bfbebSnyanmisaka }
611*437bfbebSnyanmisaka
612*437bfbebSnyanmisaka done:
613*437bfbebSnyanmisaka MPP_BUF_FUNCTION_LEAVE();
614*437bfbebSnyanmisaka return ret;
615*437bfbebSnyanmisaka }
616*437bfbebSnyanmisaka
mpp_buffer_discard(MppBufferImpl * buffer,const char * caller)617*437bfbebSnyanmisaka MPP_RET mpp_buffer_discard(MppBufferImpl *buffer, const char* caller)
618*437bfbebSnyanmisaka {
619*437bfbebSnyanmisaka MppBufferService *srv = get_srv_buffer();
620*437bfbebSnyanmisaka MppBufferGroupImpl *group = NULL;
621*437bfbebSnyanmisaka
622*437bfbebSnyanmisaka MPP_BUF_FUNCTION_ENTER();
623*437bfbebSnyanmisaka
624*437bfbebSnyanmisaka if (srv) {
625*437bfbebSnyanmisaka mpp_mutex_lock(&srv->lock);
626*437bfbebSnyanmisaka group = SEARCH_GROUP_BY_ID(srv, buffer->group_id);
627*437bfbebSnyanmisaka mpp_mutex_unlock(&srv->lock);
628*437bfbebSnyanmisaka }
629*437bfbebSnyanmisaka
630*437bfbebSnyanmisaka mpp_assert(group);
631*437bfbebSnyanmisaka if (group) {
632*437bfbebSnyanmisaka pthread_mutex_lock(&group->buf_lock);
633*437bfbebSnyanmisaka buffer->discard = 1;
634*437bfbebSnyanmisaka buf_add_log(buffer, BUF_DISCARD, caller);
635*437bfbebSnyanmisaka pthread_mutex_unlock(&group->buf_lock);
636*437bfbebSnyanmisaka }
637*437bfbebSnyanmisaka
638*437bfbebSnyanmisaka MPP_BUF_FUNCTION_LEAVE();
639*437bfbebSnyanmisaka
640*437bfbebSnyanmisaka return MPP_OK;
641*437bfbebSnyanmisaka }
642*437bfbebSnyanmisaka
mpp_buffer_get_unused(MppBufferGroupImpl * p,size_t size,const char * caller)643*437bfbebSnyanmisaka MppBufferImpl *mpp_buffer_get_unused(MppBufferGroupImpl *p, size_t size, const char* caller)
644*437bfbebSnyanmisaka {
645*437bfbebSnyanmisaka MppBufferImpl *buffer = NULL;
646*437bfbebSnyanmisaka
647*437bfbebSnyanmisaka MPP_BUF_FUNCTION_ENTER();
648*437bfbebSnyanmisaka
649*437bfbebSnyanmisaka pthread_mutex_lock(&p->buf_lock);
650*437bfbebSnyanmisaka
651*437bfbebSnyanmisaka if (!list_empty(&p->list_unused)) {
652*437bfbebSnyanmisaka MppBufferImpl *pos, *n;
653*437bfbebSnyanmisaka rk_s32 found = 0;
654*437bfbebSnyanmisaka rk_s32 search_count = 0;
655*437bfbebSnyanmisaka
656*437bfbebSnyanmisaka list_for_each_entry_safe(pos, n, &p->list_unused, MppBufferImpl, list_status) {
657*437bfbebSnyanmisaka mpp_buf_dbg(MPP_BUF_DBG_CHECK_SIZE, "request size %d on buf idx %d size %d\n",
658*437bfbebSnyanmisaka size, pos->buffer_id, pos->info.size);
659*437bfbebSnyanmisaka if (pos->info.size >= size) {
660*437bfbebSnyanmisaka buffer = pos;
661*437bfbebSnyanmisaka pthread_mutex_lock(&buffer->lock);
662*437bfbebSnyanmisaka buffer->ref_count++;
663*437bfbebSnyanmisaka buffer->used = 1;
664*437bfbebSnyanmisaka buf_add_log(buffer, BUF_REF_INC, caller);
665*437bfbebSnyanmisaka list_del_init(&buffer->list_status);
666*437bfbebSnyanmisaka list_add_tail(&buffer->list_status, &p->list_used);
667*437bfbebSnyanmisaka p->count_used++;
668*437bfbebSnyanmisaka p->count_unused--;
669*437bfbebSnyanmisaka pthread_mutex_unlock(&buffer->lock);
670*437bfbebSnyanmisaka found = 1;
671*437bfbebSnyanmisaka break;
672*437bfbebSnyanmisaka } else {
673*437bfbebSnyanmisaka if (MPP_BUFFER_INTERNAL == p->mode) {
674*437bfbebSnyanmisaka service_put_buffer(get_srv_buffer(), p, pos, 0, caller);
675*437bfbebSnyanmisaka } else
676*437bfbebSnyanmisaka search_count++;
677*437bfbebSnyanmisaka }
678*437bfbebSnyanmisaka }
679*437bfbebSnyanmisaka
680*437bfbebSnyanmisaka if (!found && search_count) {
681*437bfbebSnyanmisaka mpp_err_f("can not found match buffer with size larger than %d\n", size);
682*437bfbebSnyanmisaka mpp_buffer_group_dump(p, caller);
683*437bfbebSnyanmisaka }
684*437bfbebSnyanmisaka }
685*437bfbebSnyanmisaka
686*437bfbebSnyanmisaka pthread_mutex_unlock(&p->buf_lock);
687*437bfbebSnyanmisaka
688*437bfbebSnyanmisaka MPP_BUF_FUNCTION_LEAVE();
689*437bfbebSnyanmisaka return buffer;
690*437bfbebSnyanmisaka }
691*437bfbebSnyanmisaka
mpp_buffer_to_addr(MppBuffer buffer,size_t offset)692*437bfbebSnyanmisaka rk_u32 mpp_buffer_to_addr(MppBuffer buffer, size_t offset)
693*437bfbebSnyanmisaka {
694*437bfbebSnyanmisaka MppBufferImpl *impl = (MppBufferImpl *)buffer;
695*437bfbebSnyanmisaka rk_u32 addr = 0;
696*437bfbebSnyanmisaka
697*437bfbebSnyanmisaka if (!impl) {
698*437bfbebSnyanmisaka mpp_err_f("NULL buffer convert to zero address\n");
699*437bfbebSnyanmisaka return 0;
700*437bfbebSnyanmisaka }
701*437bfbebSnyanmisaka
702*437bfbebSnyanmisaka if (impl->info.fd >= (1 << 10)) {
703*437bfbebSnyanmisaka mpp_err_f("buffer fd %d is too large\n");
704*437bfbebSnyanmisaka return 0;
705*437bfbebSnyanmisaka }
706*437bfbebSnyanmisaka
707*437bfbebSnyanmisaka if (impl->offset + offset >= SZ_4M) {
708*437bfbebSnyanmisaka mpp_err_f("offset %d + %d is larger than 4M use extra info to send offset\n");
709*437bfbebSnyanmisaka return 0;
710*437bfbebSnyanmisaka }
711*437bfbebSnyanmisaka
712*437bfbebSnyanmisaka addr = impl->info.fd + ((impl->offset + offset) << 10);
713*437bfbebSnyanmisaka
714*437bfbebSnyanmisaka return addr;
715*437bfbebSnyanmisaka }
716*437bfbebSnyanmisaka
mpp_buffer_attach_dev_lock(const char * caller,MppBuffer buffer,MppDev dev)717*437bfbebSnyanmisaka static MppDevBufMapNode *mpp_buffer_attach_dev_lock(const char *caller, MppBuffer buffer, MppDev dev)
718*437bfbebSnyanmisaka {
719*437bfbebSnyanmisaka MppBufferImpl *impl = (MppBufferImpl *)buffer;
720*437bfbebSnyanmisaka MppDevBufMapNode *pos, *n;
721*437bfbebSnyanmisaka MppDevBufMapNode *node = NULL;
722*437bfbebSnyanmisaka MPP_RET ret = MPP_OK;
723*437bfbebSnyanmisaka
724*437bfbebSnyanmisaka mpp_dev_ioctl(dev, MPP_DEV_LOCK_MAP, NULL);
725*437bfbebSnyanmisaka
726*437bfbebSnyanmisaka pthread_mutex_lock(&impl->lock);
727*437bfbebSnyanmisaka
728*437bfbebSnyanmisaka list_for_each_entry_safe(pos, n, &impl->list_maps, MppDevBufMapNode, list_buf) {
729*437bfbebSnyanmisaka if (pos->dev == dev) {
730*437bfbebSnyanmisaka node = pos;
731*437bfbebSnyanmisaka goto DONE;
732*437bfbebSnyanmisaka }
733*437bfbebSnyanmisaka }
734*437bfbebSnyanmisaka
735*437bfbebSnyanmisaka node = (MppDevBufMapNode *)mpp_mem_pool_get(pool_buf_map_node, caller);
736*437bfbebSnyanmisaka if (!node) {
737*437bfbebSnyanmisaka mpp_err("mpp_buffer_attach_dev failed to allocate map node\n");
738*437bfbebSnyanmisaka ret = MPP_NOK;
739*437bfbebSnyanmisaka goto DONE;
740*437bfbebSnyanmisaka }
741*437bfbebSnyanmisaka
742*437bfbebSnyanmisaka INIT_LIST_HEAD(&node->list_buf);
743*437bfbebSnyanmisaka INIT_LIST_HEAD(&node->list_dev);
744*437bfbebSnyanmisaka node->lock_buf = &impl->lock;
745*437bfbebSnyanmisaka node->buffer = impl;
746*437bfbebSnyanmisaka node->dev = dev;
747*437bfbebSnyanmisaka node->pool = pool_buf_map_node;
748*437bfbebSnyanmisaka node->buf_fd = impl->info.fd;
749*437bfbebSnyanmisaka
750*437bfbebSnyanmisaka ret = mpp_dev_ioctl(dev, MPP_DEV_ATTACH_FD, node);
751*437bfbebSnyanmisaka if (ret) {
752*437bfbebSnyanmisaka mpp_mem_pool_put(pool_buf_map_node, node, caller);
753*437bfbebSnyanmisaka node = NULL;
754*437bfbebSnyanmisaka goto DONE;
755*437bfbebSnyanmisaka }
756*437bfbebSnyanmisaka list_add_tail(&node->list_buf, &impl->list_maps);
757*437bfbebSnyanmisaka
758*437bfbebSnyanmisaka DONE:
759*437bfbebSnyanmisaka pthread_mutex_unlock(&impl->lock);
760*437bfbebSnyanmisaka mpp_dev_ioctl(dev, MPP_DEV_UNLOCK_MAP, NULL);
761*437bfbebSnyanmisaka
762*437bfbebSnyanmisaka return node;
763*437bfbebSnyanmisaka }
764*437bfbebSnyanmisaka
mpp_buffer_attach_dev_f(const char * caller,MppBuffer buffer,MppDev dev)765*437bfbebSnyanmisaka MPP_RET mpp_buffer_attach_dev_f(const char *caller, MppBuffer buffer, MppDev dev)
766*437bfbebSnyanmisaka {
767*437bfbebSnyanmisaka MppDevBufMapNode *node;
768*437bfbebSnyanmisaka
769*437bfbebSnyanmisaka node = mpp_buffer_attach_dev_lock(caller, buffer, dev);
770*437bfbebSnyanmisaka
771*437bfbebSnyanmisaka return node ? MPP_OK : MPP_NOK;
772*437bfbebSnyanmisaka }
773*437bfbebSnyanmisaka
mpp_buffer_detach_dev_f(const char * caller,MppBuffer buffer,MppDev dev)774*437bfbebSnyanmisaka MPP_RET mpp_buffer_detach_dev_f(const char *caller, MppBuffer buffer, MppDev dev)
775*437bfbebSnyanmisaka {
776*437bfbebSnyanmisaka MppBufferImpl *impl = (MppBufferImpl *)buffer;
777*437bfbebSnyanmisaka MppDevBufMapNode *pos, *n;
778*437bfbebSnyanmisaka MPP_RET ret = MPP_OK;
779*437bfbebSnyanmisaka
780*437bfbebSnyanmisaka mpp_dev_ioctl(dev, MPP_DEV_LOCK_MAP, NULL);
781*437bfbebSnyanmisaka pthread_mutex_lock(&impl->lock);
782*437bfbebSnyanmisaka list_for_each_entry_safe(pos, n, &impl->list_maps, MppDevBufMapNode, list_buf) {
783*437bfbebSnyanmisaka if (pos->dev == dev) {
784*437bfbebSnyanmisaka list_del_init(&pos->list_buf);
785*437bfbebSnyanmisaka ret = mpp_dev_ioctl(dev, MPP_DEV_DETACH_FD, pos);
786*437bfbebSnyanmisaka mpp_mem_pool_put(pool_buf_map_node, pos, caller);
787*437bfbebSnyanmisaka break;
788*437bfbebSnyanmisaka }
789*437bfbebSnyanmisaka }
790*437bfbebSnyanmisaka pthread_mutex_unlock(&impl->lock);
791*437bfbebSnyanmisaka mpp_dev_ioctl(dev, MPP_DEV_UNLOCK_MAP, NULL);
792*437bfbebSnyanmisaka
793*437bfbebSnyanmisaka return ret;
794*437bfbebSnyanmisaka }
795*437bfbebSnyanmisaka
mpp_buffer_get_iova_f(const char * caller,MppBuffer buffer,MppDev dev)796*437bfbebSnyanmisaka rk_u32 mpp_buffer_get_iova_f(const char *caller, MppBuffer buffer, MppDev dev)
797*437bfbebSnyanmisaka {
798*437bfbebSnyanmisaka MppDevBufMapNode *node;
799*437bfbebSnyanmisaka
800*437bfbebSnyanmisaka node = mpp_buffer_attach_dev_lock(caller, buffer, dev);
801*437bfbebSnyanmisaka
802*437bfbebSnyanmisaka return node ? node->iova : (rk_u32)(-1);
803*437bfbebSnyanmisaka }
804*437bfbebSnyanmisaka
mpp_buffer_group_init(MppBufferGroupImpl ** group,const char * tag,const char * caller,MppBufferMode mode,MppBufferType type)805*437bfbebSnyanmisaka MPP_RET mpp_buffer_group_init(MppBufferGroupImpl **group, const char *tag, const char *caller,
806*437bfbebSnyanmisaka MppBufferMode mode, MppBufferType type)
807*437bfbebSnyanmisaka {
808*437bfbebSnyanmisaka MPP_BUF_FUNCTION_ENTER();
809*437bfbebSnyanmisaka mpp_assert(caller);
810*437bfbebSnyanmisaka
811*437bfbebSnyanmisaka *group = service_get_group(tag, caller, mode, type, 0);
812*437bfbebSnyanmisaka
813*437bfbebSnyanmisaka MPP_BUF_FUNCTION_LEAVE();
814*437bfbebSnyanmisaka return ((*group) ? (MPP_OK) : (MPP_NOK));
815*437bfbebSnyanmisaka }
816*437bfbebSnyanmisaka
mpp_buffer_group_deinit(MppBufferGroupImpl * p)817*437bfbebSnyanmisaka MPP_RET mpp_buffer_group_deinit(MppBufferGroupImpl *p)
818*437bfbebSnyanmisaka {
819*437bfbebSnyanmisaka if (!p) {
820*437bfbebSnyanmisaka mpp_err_f("found NULL pointer\n");
821*437bfbebSnyanmisaka return MPP_ERR_NULL_PTR;
822*437bfbebSnyanmisaka }
823*437bfbebSnyanmisaka
824*437bfbebSnyanmisaka MPP_BUF_FUNCTION_ENTER();
825*437bfbebSnyanmisaka
826*437bfbebSnyanmisaka service_put_group(get_srv_buffer(), p, __FUNCTION__);
827*437bfbebSnyanmisaka
828*437bfbebSnyanmisaka MPP_BUF_FUNCTION_LEAVE();
829*437bfbebSnyanmisaka return MPP_OK;
830*437bfbebSnyanmisaka }
831*437bfbebSnyanmisaka
mpp_buffer_group_reset(MppBufferGroupImpl * p)832*437bfbebSnyanmisaka MPP_RET mpp_buffer_group_reset(MppBufferGroupImpl *p)
833*437bfbebSnyanmisaka {
834*437bfbebSnyanmisaka if (!p) {
835*437bfbebSnyanmisaka mpp_err_f("found NULL pointer\n");
836*437bfbebSnyanmisaka return MPP_ERR_NULL_PTR;
837*437bfbebSnyanmisaka }
838*437bfbebSnyanmisaka
839*437bfbebSnyanmisaka MPP_BUF_FUNCTION_ENTER();
840*437bfbebSnyanmisaka
841*437bfbebSnyanmisaka pthread_mutex_lock(&p->buf_lock);
842*437bfbebSnyanmisaka
843*437bfbebSnyanmisaka buf_grp_add_log(p, GRP_RESET, NULL);
844*437bfbebSnyanmisaka
845*437bfbebSnyanmisaka if (!list_empty(&p->list_used)) {
846*437bfbebSnyanmisaka MppBufferImpl *pos, *n;
847*437bfbebSnyanmisaka
848*437bfbebSnyanmisaka list_for_each_entry_safe(pos, n, &p->list_used, MppBufferImpl, list_status) {
849*437bfbebSnyanmisaka buf_add_log(pos, BUF_DISCARD, NULL);
850*437bfbebSnyanmisaka pos->discard = 1;
851*437bfbebSnyanmisaka }
852*437bfbebSnyanmisaka }
853*437bfbebSnyanmisaka
854*437bfbebSnyanmisaka // remove unused list
855*437bfbebSnyanmisaka if (!list_empty(&p->list_unused)) {
856*437bfbebSnyanmisaka MppBufferService *srv = get_srv_buffer();
857*437bfbebSnyanmisaka MppBufferImpl *pos, *n;
858*437bfbebSnyanmisaka
859*437bfbebSnyanmisaka list_for_each_entry_safe(pos, n, &p->list_unused, MppBufferImpl, list_status) {
860*437bfbebSnyanmisaka service_put_buffer(srv, p, pos, 0, __FUNCTION__);
861*437bfbebSnyanmisaka }
862*437bfbebSnyanmisaka }
863*437bfbebSnyanmisaka
864*437bfbebSnyanmisaka pthread_mutex_unlock(&p->buf_lock);
865*437bfbebSnyanmisaka
866*437bfbebSnyanmisaka MPP_BUF_FUNCTION_LEAVE();
867*437bfbebSnyanmisaka return MPP_OK;
868*437bfbebSnyanmisaka }
869*437bfbebSnyanmisaka
mpp_buffer_group_set_callback(MppBufferGroupImpl * p,MppBufCallback callback,void * arg)870*437bfbebSnyanmisaka MPP_RET mpp_buffer_group_set_callback(MppBufferGroupImpl *p,
871*437bfbebSnyanmisaka MppBufCallback callback, void *arg)
872*437bfbebSnyanmisaka {
873*437bfbebSnyanmisaka if (!p)
874*437bfbebSnyanmisaka return MPP_OK;
875*437bfbebSnyanmisaka
876*437bfbebSnyanmisaka MPP_BUF_FUNCTION_ENTER();
877*437bfbebSnyanmisaka
878*437bfbebSnyanmisaka p->arg = arg;
879*437bfbebSnyanmisaka p->callback = callback;
880*437bfbebSnyanmisaka
881*437bfbebSnyanmisaka MPP_BUF_FUNCTION_LEAVE();
882*437bfbebSnyanmisaka return MPP_OK;
883*437bfbebSnyanmisaka }
884*437bfbebSnyanmisaka
mpp_buffer_total_now()885*437bfbebSnyanmisaka rk_u32 mpp_buffer_total_now()
886*437bfbebSnyanmisaka {
887*437bfbebSnyanmisaka MppBufferService *srv = get_srv_buffer();
888*437bfbebSnyanmisaka rk_u32 size = 0;
889*437bfbebSnyanmisaka
890*437bfbebSnyanmisaka if (srv)
891*437bfbebSnyanmisaka size = srv->total_size;
892*437bfbebSnyanmisaka
893*437bfbebSnyanmisaka return size;
894*437bfbebSnyanmisaka }
895*437bfbebSnyanmisaka
mpp_buffer_total_max()896*437bfbebSnyanmisaka rk_u32 mpp_buffer_total_max()
897*437bfbebSnyanmisaka {
898*437bfbebSnyanmisaka MppBufferService *srv = get_srv_buffer();
899*437bfbebSnyanmisaka rk_u32 size = 0;
900*437bfbebSnyanmisaka
901*437bfbebSnyanmisaka if (srv)
902*437bfbebSnyanmisaka size = srv->total_max;
903*437bfbebSnyanmisaka
904*437bfbebSnyanmisaka return size;
905*437bfbebSnyanmisaka }
906*437bfbebSnyanmisaka
type_to_flag(MppBufferType type)907*437bfbebSnyanmisaka static rk_u32 type_to_flag(MppBufferType type)
908*437bfbebSnyanmisaka {
909*437bfbebSnyanmisaka rk_u32 flag = MPP_ALLOC_FLAG_NONE;
910*437bfbebSnyanmisaka
911*437bfbebSnyanmisaka if (type & MPP_BUFFER_FLAGS_DMA32)
912*437bfbebSnyanmisaka flag += MPP_ALLOC_FLAG_DMA32;
913*437bfbebSnyanmisaka
914*437bfbebSnyanmisaka if (type & MPP_BUFFER_FLAGS_CACHABLE)
915*437bfbebSnyanmisaka flag += MPP_ALLOC_FLAG_CACHABLE;
916*437bfbebSnyanmisaka
917*437bfbebSnyanmisaka if (type & MPP_BUFFER_FLAGS_CONTIG)
918*437bfbebSnyanmisaka flag += MPP_ALLOC_FLAG_CMA;
919*437bfbebSnyanmisaka
920*437bfbebSnyanmisaka return flag;
921*437bfbebSnyanmisaka }
922*437bfbebSnyanmisaka
service_get_misc(MppBufferService * srv,MppBufferMode mode,MppBufferType type)923*437bfbebSnyanmisaka static rk_u32 service_get_misc(MppBufferService *srv, MppBufferMode mode, MppBufferType type)
924*437bfbebSnyanmisaka {
925*437bfbebSnyanmisaka rk_u32 flag = type_to_flag(type);
926*437bfbebSnyanmisaka
927*437bfbebSnyanmisaka type = (MppBufferType)(type & MPP_BUFFER_TYPE_MASK);
928*437bfbebSnyanmisaka if (type == MPP_BUFFER_TYPE_NORMAL)
929*437bfbebSnyanmisaka return 0;
930*437bfbebSnyanmisaka
931*437bfbebSnyanmisaka mpp_assert(mode < MPP_BUFFER_MODE_BUTT);
932*437bfbebSnyanmisaka mpp_assert(type < MPP_BUFFER_TYPE_BUTT);
933*437bfbebSnyanmisaka mpp_assert(flag < MPP_ALLOC_FLAG_TYPE_NB);
934*437bfbebSnyanmisaka
935*437bfbebSnyanmisaka return srv->misc[mode][type][flag];
936*437bfbebSnyanmisaka }
937*437bfbebSnyanmisaka
mpp_buffer_get_misc_group(MppBufferMode mode,MppBufferType type)938*437bfbebSnyanmisaka MppBufferGroupImpl *mpp_buffer_get_misc_group(MppBufferMode mode, MppBufferType type)
939*437bfbebSnyanmisaka {
940*437bfbebSnyanmisaka MppBufferService *srv = get_srv_buffer();
941*437bfbebSnyanmisaka MppBufferGroupImpl *misc;
942*437bfbebSnyanmisaka MppBufferType buf_type;
943*437bfbebSnyanmisaka MppMutex *lock = &srv->lock;
944*437bfbebSnyanmisaka rk_u32 id;
945*437bfbebSnyanmisaka
946*437bfbebSnyanmisaka buf_type = (MppBufferType)(type & MPP_BUFFER_TYPE_MASK);
947*437bfbebSnyanmisaka if (buf_type == MPP_BUFFER_TYPE_NORMAL)
948*437bfbebSnyanmisaka return NULL;
949*437bfbebSnyanmisaka
950*437bfbebSnyanmisaka mpp_assert(mode < MPP_BUFFER_MODE_BUTT);
951*437bfbebSnyanmisaka mpp_assert(buf_type < MPP_BUFFER_TYPE_BUTT);
952*437bfbebSnyanmisaka
953*437bfbebSnyanmisaka mpp_mutex_lock(lock);
954*437bfbebSnyanmisaka
955*437bfbebSnyanmisaka id = service_get_misc(srv, mode, type);
956*437bfbebSnyanmisaka if (!id) {
957*437bfbebSnyanmisaka char tag[32];
958*437bfbebSnyanmisaka rk_s32 offset = 0;
959*437bfbebSnyanmisaka
960*437bfbebSnyanmisaka offset += snprintf(tag + offset, sizeof(tag) - offset, "misc");
961*437bfbebSnyanmisaka offset += snprintf(tag + offset, sizeof(tag) - offset, "_%s",
962*437bfbebSnyanmisaka buf_type == MPP_BUFFER_TYPE_ION ? "ion" :
963*437bfbebSnyanmisaka buf_type == MPP_BUFFER_TYPE_DRM ? "drm" : "na");
964*437bfbebSnyanmisaka offset += snprintf(tag + offset, sizeof(tag) - offset, "_%s",
965*437bfbebSnyanmisaka mode == MPP_BUFFER_INTERNAL ? "int" : "ext");
966*437bfbebSnyanmisaka
967*437bfbebSnyanmisaka misc = service_get_group(tag, __FUNCTION__, mode, type, 1);
968*437bfbebSnyanmisaka } else
969*437bfbebSnyanmisaka misc = get_group_by_id(srv, id);
970*437bfbebSnyanmisaka mpp_mutex_unlock(lock);
971*437bfbebSnyanmisaka
972*437bfbebSnyanmisaka return misc;
973*437bfbebSnyanmisaka }
974*437bfbebSnyanmisaka
mpp_buffer_service_init()975*437bfbebSnyanmisaka static void mpp_buffer_service_init()
976*437bfbebSnyanmisaka {
977*437bfbebSnyanmisaka MppBufferService *srv = srv_buffer;
978*437bfbebSnyanmisaka rk_s32 i, j, k;
979*437bfbebSnyanmisaka
980*437bfbebSnyanmisaka if (srv)
981*437bfbebSnyanmisaka return;
982*437bfbebSnyanmisaka
983*437bfbebSnyanmisaka mpp_env_get_u32("mpp_buffer_debug", &mpp_buffer_debug, 0);
984*437bfbebSnyanmisaka
985*437bfbebSnyanmisaka srv = mpp_calloc(MppBufferService, 1);
986*437bfbebSnyanmisaka if (!srv) {
987*437bfbebSnyanmisaka mpp_err_f("alloc buffer service failed\n");
988*437bfbebSnyanmisaka return;
989*437bfbebSnyanmisaka }
990*437bfbebSnyanmisaka
991*437bfbebSnyanmisaka srv_buffer = srv;
992*437bfbebSnyanmisaka
993*437bfbebSnyanmisaka srv_status = MPP_BUF_SRV_NORMAL;
994*437bfbebSnyanmisaka pool_buf = mpp_mem_pool_init_f(MODULE_TAG, sizeof(MppBufferImpl));
995*437bfbebSnyanmisaka pool_buf_grp = mpp_mem_pool_init_f("mpp_buf_grp", sizeof(MppBufferGroupImpl));
996*437bfbebSnyanmisaka pool_buf_map_node = mpp_mem_pool_init_f("mpp_buf_map_node", sizeof(MppDevBufMapNode));
997*437bfbebSnyanmisaka
998*437bfbebSnyanmisaka srv->group_id = 1;
999*437bfbebSnyanmisaka
1000*437bfbebSnyanmisaka INIT_LIST_HEAD(&srv->list_group);
1001*437bfbebSnyanmisaka INIT_LIST_HEAD(&srv->list_orphan);
1002*437bfbebSnyanmisaka
1003*437bfbebSnyanmisaka // NOTE: Do not create misc group at beginning. Only create on when needed.
1004*437bfbebSnyanmisaka for (i = 0; i < MPP_BUFFER_MODE_BUTT; i++)
1005*437bfbebSnyanmisaka for (j = 0; j < MPP_BUFFER_TYPE_BUTT; j++)
1006*437bfbebSnyanmisaka for (k = 0; k < MPP_ALLOCATOR_WITH_FLAG_NUM; k++)
1007*437bfbebSnyanmisaka srv->misc[i][j][k] = 0;
1008*437bfbebSnyanmisaka
1009*437bfbebSnyanmisaka for (i = 0; i < (rk_s32)HASH_SIZE(srv->hash_group); i++)
1010*437bfbebSnyanmisaka INIT_HLIST_HEAD(&srv->hash_group[i]);
1011*437bfbebSnyanmisaka
1012*437bfbebSnyanmisaka mpp_mutex_init(&srv->lock);
1013*437bfbebSnyanmisaka }
1014*437bfbebSnyanmisaka
mpp_buffer_service_deinit()1015*437bfbebSnyanmisaka static void mpp_buffer_service_deinit()
1016*437bfbebSnyanmisaka {
1017*437bfbebSnyanmisaka MppBufferService *srv = srv_buffer;
1018*437bfbebSnyanmisaka rk_s32 i, j, k;
1019*437bfbebSnyanmisaka
1020*437bfbebSnyanmisaka if (!srv)
1021*437bfbebSnyanmisaka return;
1022*437bfbebSnyanmisaka
1023*437bfbebSnyanmisaka srv->finalizing = 1;
1024*437bfbebSnyanmisaka
1025*437bfbebSnyanmisaka // first remove legacy group which is the normal case
1026*437bfbebSnyanmisaka if (srv->misc_count) {
1027*437bfbebSnyanmisaka mpp_log_f("cleaning misc group\n");
1028*437bfbebSnyanmisaka for (i = 0; i < MPP_BUFFER_MODE_BUTT; i++)
1029*437bfbebSnyanmisaka for (j = 0; j < MPP_BUFFER_TYPE_BUTT; j++)
1030*437bfbebSnyanmisaka for (k = 0; k < MPP_ALLOCATOR_WITH_FLAG_NUM; k++) {
1031*437bfbebSnyanmisaka rk_u32 id = srv->misc[i][j][k];
1032*437bfbebSnyanmisaka
1033*437bfbebSnyanmisaka if (id) {
1034*437bfbebSnyanmisaka service_put_group(srv, get_group_by_id(srv, id), __FUNCTION__);
1035*437bfbebSnyanmisaka srv->misc[i][j][k] = 0;
1036*437bfbebSnyanmisaka }
1037*437bfbebSnyanmisaka }
1038*437bfbebSnyanmisaka }
1039*437bfbebSnyanmisaka
1040*437bfbebSnyanmisaka // then remove the remaining group which is the leak one
1041*437bfbebSnyanmisaka if (!list_empty(&srv->list_group)) {
1042*437bfbebSnyanmisaka MppBufferGroupImpl *pos, *n;
1043*437bfbebSnyanmisaka
1044*437bfbebSnyanmisaka if (mpp_buffer_debug & MPP_BUF_DBG_DUMP_ON_EXIT)
1045*437bfbebSnyanmisaka service_dump(srv, "leaked group found");
1046*437bfbebSnyanmisaka
1047*437bfbebSnyanmisaka mpp_log_f("cleaning leaked group\n");
1048*437bfbebSnyanmisaka list_for_each_entry_safe(pos, n, &srv->list_group, MppBufferGroupImpl, list_group) {
1049*437bfbebSnyanmisaka service_put_group(srv, pos, __FUNCTION__);
1050*437bfbebSnyanmisaka }
1051*437bfbebSnyanmisaka }
1052*437bfbebSnyanmisaka
1053*437bfbebSnyanmisaka // remove all orphan buffer group
1054*437bfbebSnyanmisaka if (!list_empty(&srv->list_orphan)) {
1055*437bfbebSnyanmisaka MppBufferGroupImpl *pos, *n;
1056*437bfbebSnyanmisaka
1057*437bfbebSnyanmisaka mpp_log_f("cleaning leaked buffer\n");
1058*437bfbebSnyanmisaka
1059*437bfbebSnyanmisaka list_for_each_entry_safe(pos, n, &srv->list_orphan, MppBufferGroupImpl, list_group) {
1060*437bfbebSnyanmisaka pos->clear_on_exit = 1;
1061*437bfbebSnyanmisaka pos->is_finalizing = 1;
1062*437bfbebSnyanmisaka service_put_group(srv, pos, __FUNCTION__);
1063*437bfbebSnyanmisaka }
1064*437bfbebSnyanmisaka }
1065*437bfbebSnyanmisaka
1066*437bfbebSnyanmisaka for (i = 0; i < MPP_BUFFER_TYPE_BUTT; i++) {
1067*437bfbebSnyanmisaka for (j = 0; j < MPP_ALLOCATOR_WITH_FLAG_NUM; j++) {
1068*437bfbebSnyanmisaka if (srv->allocator[i][j])
1069*437bfbebSnyanmisaka mpp_allocator_put(&(srv->allocator[i][j]));
1070*437bfbebSnyanmisaka }
1071*437bfbebSnyanmisaka }
1072*437bfbebSnyanmisaka mpp_mutex_destroy(&srv->lock);
1073*437bfbebSnyanmisaka
1074*437bfbebSnyanmisaka MPP_FREE(srv_buffer);
1075*437bfbebSnyanmisaka srv_status = MPP_BUF_SRV_FINALIZED;
1076*437bfbebSnyanmisaka }
1077*437bfbebSnyanmisaka
service_get_group_id(MppBufferService * srv)1078*437bfbebSnyanmisaka rk_u32 service_get_group_id(MppBufferService *srv)
1079*437bfbebSnyanmisaka {
1080*437bfbebSnyanmisaka static rk_u32 overflowed = 0;
1081*437bfbebSnyanmisaka rk_u32 id = 0;
1082*437bfbebSnyanmisaka
1083*437bfbebSnyanmisaka if (!overflowed) {
1084*437bfbebSnyanmisaka /* avoid 0 group id */
1085*437bfbebSnyanmisaka if (srv->group_id)
1086*437bfbebSnyanmisaka id = srv->group_id++;
1087*437bfbebSnyanmisaka else {
1088*437bfbebSnyanmisaka overflowed = 1;
1089*437bfbebSnyanmisaka srv->group_id = 1;
1090*437bfbebSnyanmisaka }
1091*437bfbebSnyanmisaka }
1092*437bfbebSnyanmisaka
1093*437bfbebSnyanmisaka if (overflowed) {
1094*437bfbebSnyanmisaka id = srv->group_id++;
1095*437bfbebSnyanmisaka
1096*437bfbebSnyanmisaka /* when it is overflow avoid the used id */
1097*437bfbebSnyanmisaka while (get_group_by_id(srv, id))
1098*437bfbebSnyanmisaka id = srv->group_id++;
1099*437bfbebSnyanmisaka }
1100*437bfbebSnyanmisaka
1101*437bfbebSnyanmisaka srv->group_count++;
1102*437bfbebSnyanmisaka
1103*437bfbebSnyanmisaka return id;
1104*437bfbebSnyanmisaka }
1105*437bfbebSnyanmisaka
service_get_group(const char * tag,const char * caller,MppBufferMode mode,MppBufferType type,rk_u32 is_misc)1106*437bfbebSnyanmisaka static MppBufferGroupImpl *service_get_group(const char *tag, const char *caller,
1107*437bfbebSnyanmisaka MppBufferMode mode, MppBufferType type,
1108*437bfbebSnyanmisaka rk_u32 is_misc)
1109*437bfbebSnyanmisaka {
1110*437bfbebSnyanmisaka MppBufferType buffer_type = (MppBufferType)(type & MPP_BUFFER_TYPE_MASK);
1111*437bfbebSnyanmisaka MppBufferGroupImpl *p = NULL;
1112*437bfbebSnyanmisaka MppBufferService *srv = get_srv_buffer();
1113*437bfbebSnyanmisaka MppMutex *lock;
1114*437bfbebSnyanmisaka rk_u32 flag;
1115*437bfbebSnyanmisaka rk_u32 id;
1116*437bfbebSnyanmisaka
1117*437bfbebSnyanmisaka /* env update */
1118*437bfbebSnyanmisaka mpp_env_get_u32("mpp_buffer_debug", &mpp_buffer_debug, mpp_buffer_debug);
1119*437bfbebSnyanmisaka
1120*437bfbebSnyanmisaka if (mode >= MPP_BUFFER_MODE_BUTT || buffer_type >= MPP_BUFFER_TYPE_BUTT) {
1121*437bfbebSnyanmisaka mpp_err("MppBufferService get_group found invalid mode %d type %x\n", mode, type);
1122*437bfbebSnyanmisaka return NULL;
1123*437bfbebSnyanmisaka }
1124*437bfbebSnyanmisaka
1125*437bfbebSnyanmisaka if (!srv) {
1126*437bfbebSnyanmisaka mpp_err("MppBufferService get_group failed to get service\n");
1127*437bfbebSnyanmisaka return NULL;
1128*437bfbebSnyanmisaka }
1129*437bfbebSnyanmisaka
1130*437bfbebSnyanmisaka lock = &srv->lock;
1131*437bfbebSnyanmisaka p = (MppBufferGroupImpl *)mpp_mem_pool_get(pool_buf_grp, caller);
1132*437bfbebSnyanmisaka if (!p) {
1133*437bfbebSnyanmisaka mpp_err("MppBufferService failed to allocate group context\n");
1134*437bfbebSnyanmisaka return NULL;
1135*437bfbebSnyanmisaka }
1136*437bfbebSnyanmisaka
1137*437bfbebSnyanmisaka flag = type_to_flag(type);
1138*437bfbebSnyanmisaka
1139*437bfbebSnyanmisaka p->flags = (MppAllocFlagType)flag;
1140*437bfbebSnyanmisaka
1141*437bfbebSnyanmisaka {
1142*437bfbebSnyanmisaka MppAllocator allocator = NULL;
1143*437bfbebSnyanmisaka MppAllocatorApi *alloc_api = NULL;
1144*437bfbebSnyanmisaka
1145*437bfbebSnyanmisaka mpp_mutex_lock(lock);
1146*437bfbebSnyanmisaka
1147*437bfbebSnyanmisaka allocator = srv->allocator[buffer_type][flag];
1148*437bfbebSnyanmisaka alloc_api = srv->allocator_api[buffer_type];
1149*437bfbebSnyanmisaka
1150*437bfbebSnyanmisaka // allocate general buffer first
1151*437bfbebSnyanmisaka if (!allocator) {
1152*437bfbebSnyanmisaka mpp_allocator_get(&allocator, &alloc_api, type, p->flags);
1153*437bfbebSnyanmisaka srv->allocator[buffer_type][flag] = allocator;
1154*437bfbebSnyanmisaka srv->allocator_api[buffer_type] = alloc_api;
1155*437bfbebSnyanmisaka }
1156*437bfbebSnyanmisaka
1157*437bfbebSnyanmisaka p->allocator = allocator;
1158*437bfbebSnyanmisaka p->alloc_api = alloc_api;
1159*437bfbebSnyanmisaka p->flags = mpp_allocator_get_flags(allocator);
1160*437bfbebSnyanmisaka
1161*437bfbebSnyanmisaka mpp_mutex_unlock(lock);
1162*437bfbebSnyanmisaka }
1163*437bfbebSnyanmisaka
1164*437bfbebSnyanmisaka if (!p->allocator || !p->alloc_api) {
1165*437bfbebSnyanmisaka mpp_mem_pool_put(pool_buf_grp, p, caller);
1166*437bfbebSnyanmisaka mpp_err("MppBufferService get_group failed to get allocater with mode %d type %x\n", mode, type);
1167*437bfbebSnyanmisaka return NULL;
1168*437bfbebSnyanmisaka }
1169*437bfbebSnyanmisaka
1170*437bfbebSnyanmisaka INIT_LIST_HEAD(&p->list_group);
1171*437bfbebSnyanmisaka INIT_LIST_HEAD(&p->list_used);
1172*437bfbebSnyanmisaka INIT_LIST_HEAD(&p->list_unused);
1173*437bfbebSnyanmisaka INIT_HLIST_NODE(&p->hlist);
1174*437bfbebSnyanmisaka
1175*437bfbebSnyanmisaka p->log_runtime_en = (mpp_buffer_debug & MPP_BUF_DBG_OPS_RUNTIME) ? (1) : (0);
1176*437bfbebSnyanmisaka p->log_history_en = (mpp_buffer_debug & MPP_BUF_DBG_OPS_HISTORY) ? (1) : (0);
1177*437bfbebSnyanmisaka
1178*437bfbebSnyanmisaka p->caller = caller;
1179*437bfbebSnyanmisaka p->mode = mode;
1180*437bfbebSnyanmisaka p->type = buffer_type;
1181*437bfbebSnyanmisaka p->limit = BUFFER_GROUP_SIZE_DEFAULT;
1182*437bfbebSnyanmisaka p->clear_on_exit = (mpp_buffer_debug & MPP_BUF_DBG_CLR_ON_EXIT) ? (1) : (0);
1183*437bfbebSnyanmisaka p->dump_on_exit = (mpp_buffer_debug & MPP_BUF_DBG_DUMP_ON_EXIT) ? (1) : (0);
1184*437bfbebSnyanmisaka
1185*437bfbebSnyanmisaka {
1186*437bfbebSnyanmisaka pthread_mutexattr_t attr;
1187*437bfbebSnyanmisaka
1188*437bfbebSnyanmisaka pthread_mutexattr_init(&attr);
1189*437bfbebSnyanmisaka pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
1190*437bfbebSnyanmisaka pthread_mutex_init(&p->buf_lock, &attr);
1191*437bfbebSnyanmisaka pthread_mutexattr_destroy(&attr);
1192*437bfbebSnyanmisaka }
1193*437bfbebSnyanmisaka
1194*437bfbebSnyanmisaka if (p->log_history_en)
1195*437bfbebSnyanmisaka p->logs = buf_logs_init(BUFFER_OPS_MAX_COUNT);
1196*437bfbebSnyanmisaka
1197*437bfbebSnyanmisaka mpp_mutex_lock(lock);
1198*437bfbebSnyanmisaka
1199*437bfbebSnyanmisaka id = service_get_group_id(srv);
1200*437bfbebSnyanmisaka if (tag) {
1201*437bfbebSnyanmisaka snprintf(p->tag, sizeof(p->tag) - 1, "%s_%d", tag, id);
1202*437bfbebSnyanmisaka } else {
1203*437bfbebSnyanmisaka snprintf(p->tag, sizeof(p->tag) - 1, "unknown");
1204*437bfbebSnyanmisaka }
1205*437bfbebSnyanmisaka p->group_id = id;
1206*437bfbebSnyanmisaka
1207*437bfbebSnyanmisaka list_add_tail(&p->list_group, &srv->list_group);
1208*437bfbebSnyanmisaka hash_add(srv->hash_group, &p->hlist, id);
1209*437bfbebSnyanmisaka
1210*437bfbebSnyanmisaka buf_grp_add_log(p, GRP_CREATE, caller);
1211*437bfbebSnyanmisaka
1212*437bfbebSnyanmisaka if (is_misc) {
1213*437bfbebSnyanmisaka srv->misc[mode][buffer_type][flag] = id;
1214*437bfbebSnyanmisaka p->is_misc = 1;
1215*437bfbebSnyanmisaka srv->misc_count++;
1216*437bfbebSnyanmisaka }
1217*437bfbebSnyanmisaka
1218*437bfbebSnyanmisaka mpp_mutex_unlock(lock);
1219*437bfbebSnyanmisaka
1220*437bfbebSnyanmisaka return p;
1221*437bfbebSnyanmisaka }
1222*437bfbebSnyanmisaka
destroy_group(MppBufferService * srv,MppBufferGroupImpl * group)1223*437bfbebSnyanmisaka static void destroy_group(MppBufferService *srv, MppBufferGroupImpl *group)
1224*437bfbebSnyanmisaka {
1225*437bfbebSnyanmisaka mpp_assert(group->count_used == 0);
1226*437bfbebSnyanmisaka mpp_assert(group->count_unused == 0);
1227*437bfbebSnyanmisaka
1228*437bfbebSnyanmisaka if (group->count_unused || group->count_used) {
1229*437bfbebSnyanmisaka mpp_err("mpp_buffer_group %s deinit mismatch counter used %4d unused %4d found\n",
1230*437bfbebSnyanmisaka group->caller, group->count_used, group->count_unused);
1231*437bfbebSnyanmisaka group->count_unused = 0;
1232*437bfbebSnyanmisaka group->count_used = 0;
1233*437bfbebSnyanmisaka }
1234*437bfbebSnyanmisaka
1235*437bfbebSnyanmisaka buf_grp_add_log(group, GRP_DESTROY, __FUNCTION__);
1236*437bfbebSnyanmisaka
1237*437bfbebSnyanmisaka list_del_init(&group->list_group);
1238*437bfbebSnyanmisaka hash_del(&group->hlist);
1239*437bfbebSnyanmisaka pthread_mutex_destroy(&group->buf_lock);
1240*437bfbebSnyanmisaka
1241*437bfbebSnyanmisaka if (group->logs) {
1242*437bfbebSnyanmisaka buf_logs_deinit(group->logs);
1243*437bfbebSnyanmisaka group->logs = NULL;
1244*437bfbebSnyanmisaka }
1245*437bfbebSnyanmisaka
1246*437bfbebSnyanmisaka if (srv) {
1247*437bfbebSnyanmisaka MppBufferMode mode = group->mode;
1248*437bfbebSnyanmisaka MppBufferType type = group->type;
1249*437bfbebSnyanmisaka rk_u32 flag = type_to_flag(type);
1250*437bfbebSnyanmisaka rk_u32 id = group->group_id;
1251*437bfbebSnyanmisaka
1252*437bfbebSnyanmisaka srv->group_count--;
1253*437bfbebSnyanmisaka
1254*437bfbebSnyanmisaka if (id == srv->misc[mode][type][flag]) {
1255*437bfbebSnyanmisaka srv->misc[mode][type][flag] = 0;
1256*437bfbebSnyanmisaka srv->misc_count--;
1257*437bfbebSnyanmisaka }
1258*437bfbebSnyanmisaka }
1259*437bfbebSnyanmisaka
1260*437bfbebSnyanmisaka if (pool_buf_grp)
1261*437bfbebSnyanmisaka mpp_mem_pool_put_f(pool_buf_grp, group);
1262*437bfbebSnyanmisaka }
1263*437bfbebSnyanmisaka
service_put_group(MppBufferService * srv,MppBufferGroupImpl * p,const char * caller)1264*437bfbebSnyanmisaka static void service_put_group(MppBufferService *srv, MppBufferGroupImpl *p, const char *caller)
1265*437bfbebSnyanmisaka {
1266*437bfbebSnyanmisaka MppMutex *lock;
1267*437bfbebSnyanmisaka
1268*437bfbebSnyanmisaka if (!srv)
1269*437bfbebSnyanmisaka return;
1270*437bfbebSnyanmisaka
1271*437bfbebSnyanmisaka lock = &srv->lock;
1272*437bfbebSnyanmisaka
1273*437bfbebSnyanmisaka if (!srv->finalizing)
1274*437bfbebSnyanmisaka mpp_mutex_lock(lock);
1275*437bfbebSnyanmisaka
1276*437bfbebSnyanmisaka buf_grp_add_log(p, GRP_RELEASE, caller);
1277*437bfbebSnyanmisaka
1278*437bfbebSnyanmisaka // remove unused list
1279*437bfbebSnyanmisaka if (!list_empty(&p->list_unused)) {
1280*437bfbebSnyanmisaka MppBufferImpl *pos, *n;
1281*437bfbebSnyanmisaka
1282*437bfbebSnyanmisaka list_for_each_entry_safe(pos, n, &p->list_unused, MppBufferImpl, list_status) {
1283*437bfbebSnyanmisaka service_put_buffer(srv, p, pos, 0, caller);
1284*437bfbebSnyanmisaka }
1285*437bfbebSnyanmisaka }
1286*437bfbebSnyanmisaka
1287*437bfbebSnyanmisaka if (list_empty(&p->list_used)) {
1288*437bfbebSnyanmisaka destroy_group(srv, p);
1289*437bfbebSnyanmisaka } else {
1290*437bfbebSnyanmisaka if (!srv->finalizing || (srv->finalizing && p->dump_on_exit)) {
1291*437bfbebSnyanmisaka mpp_err("mpp_group %p tag %s caller %s mode %s type %s deinit with %d bytes not released\n",
1292*437bfbebSnyanmisaka p, p->tag, p->caller, mode2str[p->mode], type2str[p->type], p->usage);
1293*437bfbebSnyanmisaka
1294*437bfbebSnyanmisaka mpp_buffer_group_dump(p, caller);
1295*437bfbebSnyanmisaka }
1296*437bfbebSnyanmisaka
1297*437bfbebSnyanmisaka /* if clear on exit we need to release remaining buffer */
1298*437bfbebSnyanmisaka if (p->clear_on_exit) {
1299*437bfbebSnyanmisaka MppBufferImpl *pos, *n;
1300*437bfbebSnyanmisaka
1301*437bfbebSnyanmisaka if (p->dump_on_exit)
1302*437bfbebSnyanmisaka mpp_err("force release all remaining buffer\n");
1303*437bfbebSnyanmisaka
1304*437bfbebSnyanmisaka list_for_each_entry_safe(pos, n, &p->list_used, MppBufferImpl, list_status) {
1305*437bfbebSnyanmisaka if (p->dump_on_exit)
1306*437bfbebSnyanmisaka mpp_err("clearing buffer %p\n", pos);
1307*437bfbebSnyanmisaka pos->ref_count = 0;
1308*437bfbebSnyanmisaka pos->discard = 1;
1309*437bfbebSnyanmisaka service_put_buffer(srv, p, pos, 0, caller);
1310*437bfbebSnyanmisaka }
1311*437bfbebSnyanmisaka
1312*437bfbebSnyanmisaka destroy_group(srv, p);
1313*437bfbebSnyanmisaka } else {
1314*437bfbebSnyanmisaka // otherwise move the group to list_orphan and wait for buffer release
1315*437bfbebSnyanmisaka buf_grp_add_log(p, GRP_ORPHAN, caller);
1316*437bfbebSnyanmisaka list_del_init(&p->list_group);
1317*437bfbebSnyanmisaka list_add_tail(&p->list_group, &srv->list_orphan);
1318*437bfbebSnyanmisaka p->is_orphan = 1;
1319*437bfbebSnyanmisaka }
1320*437bfbebSnyanmisaka }
1321*437bfbebSnyanmisaka
1322*437bfbebSnyanmisaka if (!srv->finalizing)
1323*437bfbebSnyanmisaka mpp_mutex_unlock(lock);
1324*437bfbebSnyanmisaka }
1325*437bfbebSnyanmisaka
1326*437bfbebSnyanmisaka
service_dump(MppBufferService * srv,const char * info)1327*437bfbebSnyanmisaka static void service_dump(MppBufferService *srv, const char *info)
1328*437bfbebSnyanmisaka {
1329*437bfbebSnyanmisaka MppBufferGroupImpl *group;
1330*437bfbebSnyanmisaka struct hlist_node *n;
1331*437bfbebSnyanmisaka rk_u32 key;
1332*437bfbebSnyanmisaka
1333*437bfbebSnyanmisaka mpp_mutex_lock(&srv->lock);
1334*437bfbebSnyanmisaka
1335*437bfbebSnyanmisaka mpp_log("dumping all buffer groups for %s\n", info);
1336*437bfbebSnyanmisaka
1337*437bfbebSnyanmisaka if (hash_empty(srv->hash_group)) {
1338*437bfbebSnyanmisaka mpp_log("no buffer group can be dumped\n");
1339*437bfbebSnyanmisaka } else {
1340*437bfbebSnyanmisaka hash_for_each_safe(srv->hash_group, key, n, group, hlist) {
1341*437bfbebSnyanmisaka mpp_buffer_group_dump(group, __FUNCTION__);
1342*437bfbebSnyanmisaka }
1343*437bfbebSnyanmisaka }
1344*437bfbebSnyanmisaka
1345*437bfbebSnyanmisaka mpp_mutex_unlock(&srv->lock);
1346*437bfbebSnyanmisaka }
1347*437bfbebSnyanmisaka
1348*437bfbebSnyanmisaka MPP_SINGLETON(MPP_SGLN_BUFFER, mpp_buffer, mpp_buffer_service_init, mpp_buffer_service_deinit)
1349