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