xref: /OK3568_Linux_fs/external/mpp/osal/mpp_allocator.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright 2015 Rockchip Electronics Co. LTD
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define MODULE_TAG "mpp_allocator"
18 
19 #include "mpp_mem.h"
20 #include "mpp_debug.h"
21 #include "mpp_common.h"
22 #include "mpp_allocator.h"
23 #include "mpp_allocator_impl.h"
24 
25 #include "os_allocator.h"
26 
27 #include <linux/drm.h>
28 
29 #define MPP_ALLOCATOR_LOCK(p)   pthread_mutex_lock(&(p)->lock);
30 #define MPP_ALLOCATOR_UNLOCK(p) pthread_mutex_unlock(&(p)->lock);
31 
32 typedef enum OsAllocatorApiId_e {
33     ALLOC_API_ALLOC,
34     ALLOC_API_FREE,
35     ALLOC_API_IMPORT,
36     ALLOC_API_RELEASE,
37     ALLOC_API_MMAP,
38     ALLOC_API_BUTT,
39 } OsAllocatorApiId;
40 
mpp_allocator_api_wrapper(MppAllocator allocator,MppBufferInfo * info,OsAllocatorApiId id)41 static MPP_RET mpp_allocator_api_wrapper(MppAllocator allocator,
42                                          MppBufferInfo *info,
43                                          OsAllocatorApiId id)
44 {
45     if (NULL == allocator || NULL == info || id >= ALLOC_API_BUTT) {
46         mpp_err_f("invalid input: allocator %p info %p id %d\n",
47                   allocator, info, id);
48         return MPP_ERR_UNKNOW;
49     }
50 
51     MPP_RET ret = MPP_NOK;
52     MppAllocatorImpl *p = (MppAllocatorImpl *)allocator;
53     OsAllocatorFunc func;
54 
55     MPP_ALLOCATOR_LOCK(p);
56     switch (id) {
57     case ALLOC_API_ALLOC : {
58         func = p->os_api.alloc;
59     } break;
60     case ALLOC_API_FREE : {
61         func = p->os_api.free;
62     } break;
63     case ALLOC_API_IMPORT : {
64         func = p->os_api.import;
65     } break;
66     case ALLOC_API_RELEASE : {
67         func = p->os_api.release;
68     } break;
69     case ALLOC_API_MMAP : {
70         func = p->os_api.mmap;
71     } break;
72     default : {
73         func = NULL;
74     } break;
75     }
76 
77     if (func && p->ctx)
78         ret = func(p->ctx, info);
79 
80     MPP_ALLOCATOR_UNLOCK(p);
81 
82     return ret;
83 }
84 
mpp_allocator_alloc(MppAllocator allocator,MppBufferInfo * info)85 static MPP_RET mpp_allocator_alloc(MppAllocator allocator, MppBufferInfo *info)
86 {
87     return mpp_allocator_api_wrapper(allocator, info, ALLOC_API_ALLOC);
88 }
89 
mpp_allocator_free(MppAllocator allocator,MppBufferInfo * info)90 static MPP_RET mpp_allocator_free(MppAllocator allocator, MppBufferInfo *info)
91 {
92     return mpp_allocator_api_wrapper(allocator, info, ALLOC_API_FREE);
93 }
94 
mpp_allocator_import(MppAllocator allocator,MppBufferInfo * info)95 static MPP_RET mpp_allocator_import(MppAllocator allocator, MppBufferInfo *info)
96 {
97     return mpp_allocator_api_wrapper(allocator, info, ALLOC_API_IMPORT);
98 }
99 
mpp_allocator_release(MppAllocator allocator,MppBufferInfo * info)100 static MPP_RET mpp_allocator_release(MppAllocator allocator,
101                                      MppBufferInfo *info)
102 {
103     return mpp_allocator_api_wrapper(allocator, info, ALLOC_API_RELEASE);
104 }
105 
mpp_allocator_mmap(MppAllocator allocator,MppBufferInfo * info)106 static MPP_RET mpp_allocator_mmap(MppAllocator allocator, MppBufferInfo *info)
107 {
108     return mpp_allocator_api_wrapper(allocator, info, ALLOC_API_MMAP);
109 }
110 
111 static MppAllocatorApi mpp_allocator_api = {
112     .size = sizeof(mpp_allocator_api),
113     .version = 1,
114     .alloc = mpp_allocator_alloc,
115     .free = mpp_allocator_free,
116     .import = mpp_allocator_import,
117     .release =  mpp_allocator_release,
118     .mmap  = mpp_allocator_mmap,
119 };
120 
mpp_allocator_get(MppAllocator * allocator,MppAllocatorApi ** api,MppBufferType type)121 MPP_RET mpp_allocator_get(MppAllocator *allocator,
122                           MppAllocatorApi **api, MppBufferType type)
123 {
124     MppBufferType buffer_type = (MppBufferType)(type & MPP_BUFFER_TYPE_MASK);
125     RK_U32 flags = (type & MPP_BUFFER_FLAGS_MASK) >> 16;
126 
127     if (NULL == allocator || NULL == api || buffer_type >= MPP_BUFFER_TYPE_BUTT) {
128         mpp_err_f("invalid input: allocator %p api %p type %d\n",
129                   allocator, api, buffer_type);
130         return MPP_ERR_UNKNOW;
131     }
132 
133     MppAllocatorImpl *p = mpp_malloc(MppAllocatorImpl, 1);
134     if (NULL == p) {
135         mpp_err("mpp_allocator_get failed to malloc allocator context\n");
136         return MPP_ERR_NULL_PTR;
137     } else {
138         p->type = buffer_type;
139         p->flags = flags;
140     }
141 
142     MPP_RET ret = os_allocator_get(&p->os_api, buffer_type);
143 
144     if (MPP_OK == ret) {
145         MppAllocatorCfg cfg = {
146             .alignment = SZ_4K,
147             .flags = flags,
148         };
149         ret = p->os_api.open(&p->ctx, &cfg);
150     }
151     if (MPP_OK == ret) {
152         pthread_mutexattr_t attr;
153         pthread_mutexattr_init(&attr);
154         pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
155         pthread_mutex_init(&p->lock, &attr);
156         pthread_mutexattr_destroy(&attr);
157 
158         *allocator  = p;
159         *api        = &mpp_allocator_api;
160     } else {
161         mpp_err("mpp_allocator_get type %d failed\n", type);
162         mpp_free(p);
163         *allocator  = NULL;
164         *api        = NULL;
165     }
166 
167     return ret;
168 }
169 
mpp_allocator_put(MppAllocator * allocator)170 MPP_RET mpp_allocator_put(MppAllocator *allocator)
171 {
172     if (NULL == allocator) {
173         mpp_err_f("invalid input: allocator %p\n", allocator);
174         return MPP_ERR_NULL_PTR;
175     }
176 
177     MppAllocatorImpl *p = (MppAllocatorImpl *)*allocator;
178 
179     if (!p)
180         return MPP_OK;
181     *allocator = NULL;
182 
183     if (p->os_api.close && p->ctx)
184         p->os_api.close(p->ctx);
185     pthread_mutex_destroy(&p->lock);
186     mpp_free(p);
187 
188     return MPP_OK;
189 }
190 
get_real_allocator_type(const MppAllocator allocator)191 MppBufferType get_real_allocator_type(const MppAllocator allocator)
192 {
193     MppAllocatorImpl *p = (MppAllocatorImpl *)allocator;
194     MppBufferType type = allocator ? p->os_api.type : MPP_BUFFER_TYPE_BUTT;
195 
196     return type;
197 }