3 * Copyright 2012 Samsung Electronics S.LSI Co. LTD
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 * @file Exynos_OSAL_SharedMemory.c
21 * @author SeungBeom Kim (sbcrux.kim@samsung.com)
22 * Jinsung Yang (jsgood.yang@samsung.com)
23 * Taehwan Kim (t_h.kim@samsung.com)
34 #include <cutils/log.h>
35 #include <cutils/atomic.h>
40 #include "exynos_ion.h"
42 #include "Exynos_OSAL_Mutex.h"
43 #include "Exynos_OSAL_Memory.h"
44 #include "Exynos_OSAL_SharedMemory.h"
46 #include "Exynos_OSAL_ETC.h"
48 //#define EXYNOS_LOG_OFF
49 #include "Exynos_OSAL_Log.h"
52 static int mem_cnt
= 0;
53 static int map_cnt
= 0;
55 struct EXYNOS_SHAREDMEM_LIST
;
56 typedef struct _EXYNOS_SHAREDMEM_LIST
62 struct _EXYNOS_SHAREDMEM_LIST
*pNextMemory
;
63 } EXYNOS_SHAREDMEM_LIST
;
65 typedef struct _EXYNOS_SHARED_MEMORY
68 EXYNOS_SHAREDMEM_LIST
*pAllocMemory
;
69 OMX_HANDLETYPE hSMMutex
;
70 } EXYNOS_SHARED_MEMORY
;
73 OMX_HANDLETYPE
Exynos_OSAL_SharedMemory_Open()
75 EXYNOS_SHARED_MEMORY
*pHandle
= NULL
;
78 pHandle
= (EXYNOS_SHARED_MEMORY
*)Exynos_OSAL_Malloc(sizeof(EXYNOS_SHARED_MEMORY
));
81 Exynos_OSAL_Memset(pHandle
, 0, sizeof(EXYNOS_SHARED_MEMORY
));
83 IONClient
= ion_open();
85 Exynos_OSAL_Log(EXYNOS_LOG_ERROR
, "ion_open is failed: %d", IONClient
);
86 Exynos_OSAL_Free((void *)pHandle
);
91 pHandle
->hIONHandle
= IONClient
;
93 if (OMX_ErrorNone
!= Exynos_OSAL_MutexCreate(&pHandle
->hSMMutex
)) {
94 Exynos_OSAL_Log(EXYNOS_LOG_ERROR
, "Exynos_OSAL_MutexCreate(hSMMutex) is failed");
95 /* free a ion_client */
96 ion_close(pHandle
->hIONHandle
);
97 pHandle
->hIONHandle
= -1;
99 Exynos_OSAL_Free((void *)pHandle
);
104 return (OMX_HANDLETYPE
)pHandle
;
107 void Exynos_OSAL_SharedMemory_Close(OMX_HANDLETYPE handle
)
109 EXYNOS_SHARED_MEMORY
*pHandle
= (EXYNOS_SHARED_MEMORY
*)handle
;
110 EXYNOS_SHAREDMEM_LIST
*pSMList
= NULL
;
111 EXYNOS_SHAREDMEM_LIST
*pCurrentElement
= NULL
;
112 EXYNOS_SHAREDMEM_LIST
*pDeleteElement
= NULL
;
117 Exynos_OSAL_MutexLock(pHandle
->hSMMutex
);
118 pCurrentElement
= pSMList
= pHandle
->pAllocMemory
;
120 while (pCurrentElement
!= NULL
) {
121 pDeleteElement
= pCurrentElement
;
122 pCurrentElement
= pCurrentElement
->pNextMemory
;
124 /* if mmap was not called, mapAddr is same as IONBuffer */
125 if (pDeleteElement
->mapAddr
!= INT_TO_PTR(pDeleteElement
->IONBuffer
)) {
126 if (munmap(pDeleteElement
->mapAddr
, pDeleteElement
->allocSize
))
127 Exynos_OSAL_Log(EXYNOS_LOG_ERROR
, "munmap is failed");
130 pDeleteElement
->mapAddr
= NULL
;
131 pDeleteElement
->allocSize
= 0;
133 if (pDeleteElement
->owner
) {
134 /* free a ion_buffer */
135 ion_close(pDeleteElement
->IONBuffer
);
138 pDeleteElement
->IONBuffer
= 0;
140 Exynos_OSAL_Free(pDeleteElement
);
142 Exynos_OSAL_Log(EXYNOS_LOG_TRACE
, "SharedMemory mem count: %d", mem_cnt
);
145 pHandle
->pAllocMemory
= pSMList
= NULL
;
146 Exynos_OSAL_MutexUnlock(pHandle
->hSMMutex
);
148 Exynos_OSAL_MutexTerminate(pHandle
->hSMMutex
);
149 pHandle
->hSMMutex
= NULL
;
151 /* free a ion_client */
152 ion_close(pHandle
->hIONHandle
);
153 pHandle
->hIONHandle
= -1;
155 Exynos_OSAL_Free(pHandle
);
161 OMX_PTR
Exynos_OSAL_SharedMemory_Alloc(OMX_HANDLETYPE handle
, OMX_U32 size
, MEMORY_TYPE memoryType
)
163 EXYNOS_SHARED_MEMORY
*pHandle
= (EXYNOS_SHARED_MEMORY
*)handle
;
164 EXYNOS_SHAREDMEM_LIST
*pSMList
= NULL
;
165 EXYNOS_SHAREDMEM_LIST
*pElement
= NULL
;
166 EXYNOS_SHAREDMEM_LIST
*pCurrentElement
= NULL
;
167 OMX_S32 IONBuffer
= 0;
168 OMX_PTR pBuffer
= NULL
;
175 pElement
= (EXYNOS_SHAREDMEM_LIST
*)Exynos_OSAL_Malloc(sizeof(EXYNOS_SHAREDMEM_LIST
));
176 if (pElement
== NULL
)
178 Exynos_OSAL_Memset(pElement
, 0, sizeof(EXYNOS_SHAREDMEM_LIST
));
179 pElement
->owner
= OMX_TRUE
;
181 /* priority is like as EXT > SECURE > CONTIG > CACHED > NORMAL */
182 switch ((int)memoryType
) {
183 case (EXT_MEMORY
| SECURE_MEMORY
| CONTIG_MEMORY
| CACHED_MEMORY
): /* EXTRA */
184 case (EXT_MEMORY
| SECURE_MEMORY
| CONTIG_MEMORY
):
185 case (EXT_MEMORY
| SECURE_MEMORY
| CACHED_MEMORY
):
186 case (EXT_MEMORY
| SECURE_MEMORY
):
187 mask
= ION_HEAP_EXYNOS_CONTIG_MASK
;
188 flag
= ION_EXYNOS_VIDEO_EXT_MASK
| ION_FLAG_PROTECTED
;
190 case (EXT_MEMORY
| CONTIG_MEMORY
| CACHED_MEMORY
):
191 case (EXT_MEMORY
| CONTIG_MEMORY
):
192 case (EXT_MEMORY
| CACHED_MEMORY
):
194 mask
= ION_HEAP_EXYNOS_CONTIG_MASK
;
195 flag
= ION_EXYNOS_VIDEO_EXT_MASK
;
197 case (SECURE_MEMORY
| CONTIG_MEMORY
| CACHED_MEMORY
): /* SECURE */
198 case (SECURE_MEMORY
| CONTIG_MEMORY
):
199 case (SECURE_MEMORY
| CACHED_MEMORY
):
201 mask
= ION_HEAP_EXYNOS_CONTIG_MASK
;
202 flag
= ION_EXYNOS_MFC_INPUT_MASK
| ION_FLAG_PROTECTED
;
204 case (CONTIG_MEMORY
| CACHED_MEMORY
): /* CONTIG */
206 mask
= ION_HEAP_EXYNOS_CONTIG_MASK
;
207 flag
= ION_EXYNOS_MFC_INPUT_MASK
;
209 case CACHED_MEMORY
: /* CACHED */
210 mask
= ION_HEAP_SYSTEM_MASK
;
211 flag
= ION_FLAG_CACHED
;
213 default: /* NORMAL */
214 mask
= ION_HEAP_SYSTEM_MASK
;
215 flag
= ION_FLAG_CACHED
;
219 #ifdef USE_IMPROVED_BUFFER
220 if (flag
& ION_FLAG_CACHED
) /* use improved cache oprs */
221 flag
|= ION_FLAG_CACHED_NEEDS_SYNC
;
224 if (ion_alloc_fd(pHandle
->hIONHandle
, size
, 0, mask
, flag
, (int *)&IONBuffer
) < 0) {
225 Exynos_OSAL_Log(EXYNOS_LOG_WARNING
, "ion_alloc_fd is failed(mask:%x, flag:%x)", mask
, flag
);
226 if (memoryType
== CONTIG_MEMORY
) {
227 /* retry at normal area */
229 if (ion_alloc_fd(pHandle
->hIONHandle
, size
, 0, mask
, flag
, (int *)&IONBuffer
) < 0)
230 Exynos_OSAL_Log(EXYNOS_LOG_ERROR
, "retry, ion_alloc_fd is failed(mask:%x, flag:%x)", mask
, flag
);
235 Exynos_OSAL_Log(EXYNOS_LOG_ERROR
, "ion buffer is wrong: fd = %d", IONBuffer
);
236 Exynos_OSAL_Free((OMX_PTR
)pElement
);
240 if (flag
& ION_FLAG_PROTECTED
) {
241 /* in case of DRM, do not call mmap. so set a fd instead of vaddr */
242 pBuffer
= INT_TO_PTR(IONBuffer
);
244 pBuffer
= mmap(NULL
, size
, PROT_READ
| PROT_WRITE
, MAP_SHARED
, IONBuffer
, 0);
245 if (pBuffer
== MAP_FAILED
) {
246 Exynos_OSAL_Log(EXYNOS_LOG_ERROR
, "mmap is failed(size:%d)", size
);
247 /* free a ion_buffer */
248 ion_close(IONBuffer
);
249 Exynos_OSAL_Free((OMX_PTR
)pElement
);
255 pElement
->IONBuffer
= IONBuffer
;
256 pElement
->mapAddr
= pBuffer
;
257 pElement
->allocSize
= size
;
258 pElement
->pNextMemory
= NULL
;
260 Exynos_OSAL_MutexLock(pHandle
->hSMMutex
);
261 pSMList
= pHandle
->pAllocMemory
;
262 if (pSMList
== NULL
) {
263 pHandle
->pAllocMemory
= pSMList
= pElement
;
265 pCurrentElement
= pSMList
;
266 while (pCurrentElement
->pNextMemory
!= NULL
) {
267 pCurrentElement
= pCurrentElement
->pNextMemory
;
269 pCurrentElement
->pNextMemory
= pElement
;
271 Exynos_OSAL_MutexUnlock(pHandle
->hSMMutex
);
274 Exynos_OSAL_Log(EXYNOS_LOG_TRACE
, "SharedMemory mem count: %d", mem_cnt
);
280 void Exynos_OSAL_SharedMemory_Free(OMX_HANDLETYPE handle
, OMX_PTR pBuffer
)
282 EXYNOS_SHARED_MEMORY
*pHandle
= (EXYNOS_SHARED_MEMORY
*)handle
;
283 EXYNOS_SHAREDMEM_LIST
*pSMList
= NULL
;
284 EXYNOS_SHAREDMEM_LIST
*pCurrentElement
= NULL
;
285 EXYNOS_SHAREDMEM_LIST
*pDeleteElement
= NULL
;
290 Exynos_OSAL_MutexLock(pHandle
->hSMMutex
);
291 pSMList
= pHandle
->pAllocMemory
;
292 if (pSMList
== NULL
) {
293 Exynos_OSAL_MutexUnlock(pHandle
->hSMMutex
);
297 pCurrentElement
= pSMList
;
298 if (pSMList
->mapAddr
== pBuffer
) {
299 pDeleteElement
= pSMList
;
300 pHandle
->pAllocMemory
= pSMList
= pSMList
->pNextMemory
;
302 while ((pCurrentElement
!= NULL
) && (((EXYNOS_SHAREDMEM_LIST
*)(pCurrentElement
->pNextMemory
)) != NULL
) &&
303 (((EXYNOS_SHAREDMEM_LIST
*)(pCurrentElement
->pNextMemory
))->mapAddr
!= pBuffer
))
304 pCurrentElement
= pCurrentElement
->pNextMemory
;
306 if ((((EXYNOS_SHAREDMEM_LIST
*)(pCurrentElement
->pNextMemory
)) != NULL
) &&
307 (((EXYNOS_SHAREDMEM_LIST
*)(pCurrentElement
->pNextMemory
))->mapAddr
== pBuffer
)) {
308 pDeleteElement
= pCurrentElement
->pNextMemory
;
309 pCurrentElement
->pNextMemory
= pDeleteElement
->pNextMemory
;
311 Exynos_OSAL_MutexUnlock(pHandle
->hSMMutex
);
312 Exynos_OSAL_Log(EXYNOS_LOG_ERROR
, "Can not find SharedMemory");
316 Exynos_OSAL_MutexUnlock(pHandle
->hSMMutex
);
318 if (pDeleteElement
->mapAddr
!= INT_TO_PTR(pDeleteElement
->IONBuffer
)) {
319 if (munmap(pDeleteElement
->mapAddr
, pDeleteElement
->allocSize
)) {
320 Exynos_OSAL_Log(EXYNOS_LOG_ERROR
, "munmap is failed");
325 pDeleteElement
->mapAddr
= NULL
;
326 pDeleteElement
->allocSize
= 0;
328 if (pDeleteElement
->owner
) {
329 /* free a ion_buffer */
330 ion_close(pDeleteElement
->IONBuffer
);
333 pDeleteElement
->IONBuffer
= 0;
335 Exynos_OSAL_Free(pDeleteElement
);
337 Exynos_OSAL_Log(EXYNOS_LOG_TRACE
, "SharedMemory mem count: %d", mem_cnt
);
344 OMX_PTR
Exynos_OSAL_SharedMemory_Map(OMX_HANDLETYPE handle
, OMX_U32 size
, unsigned int ionfd
)
346 EXYNOS_SHARED_MEMORY
*pHandle
= (EXYNOS_SHARED_MEMORY
*)handle
;
347 EXYNOS_SHAREDMEM_LIST
*pSMList
= NULL
;
348 EXYNOS_SHAREDMEM_LIST
*pElement
= NULL
;
349 EXYNOS_SHAREDMEM_LIST
*pCurrentElement
= NULL
;
350 OMX_S32 IONBuffer
= 0;
351 OMX_PTR pBuffer
= NULL
;
356 pElement
= (EXYNOS_SHAREDMEM_LIST
*)Exynos_OSAL_Malloc(sizeof(EXYNOS_SHAREDMEM_LIST
));
357 Exynos_OSAL_Memset(pElement
, 0, sizeof(EXYNOS_SHAREDMEM_LIST
));
359 IONBuffer
= (OMX_S32
)ionfd
;
361 if (IONBuffer
<= 0) {
362 Exynos_OSAL_Log(EXYNOS_LOG_ERROR
, "ionFD(%d) is wrong", IONBuffer
);
363 Exynos_OSAL_Free((void*)pElement
);
367 pBuffer
= mmap(NULL
, size
, PROT_READ
| PROT_WRITE
, MAP_SHARED
, IONBuffer
, 0);
368 if (pBuffer
== NULL
) {
369 Exynos_OSAL_Log(EXYNOS_LOG_ERROR
, "mmap is failed(size:%d)", size
);
370 /* free a ion_buffer */
371 ion_close(IONBuffer
);
372 Exynos_OSAL_Free((void*)pElement
);
376 pElement
->IONBuffer
= IONBuffer
;
377 pElement
->mapAddr
= pBuffer
;
378 pElement
->allocSize
= size
;
379 pElement
->pNextMemory
= NULL
;
381 Exynos_OSAL_MutexLock(pHandle
->hSMMutex
);
382 pSMList
= pHandle
->pAllocMemory
;
383 if (pSMList
== NULL
) {
384 pHandle
->pAllocMemory
= pSMList
= pElement
;
386 pCurrentElement
= pSMList
;
387 while (pCurrentElement
->pNextMemory
!= NULL
) {
388 pCurrentElement
= pCurrentElement
->pNextMemory
;
390 pCurrentElement
->pNextMemory
= pElement
;
392 Exynos_OSAL_MutexUnlock(pHandle
->hSMMutex
);
395 Exynos_OSAL_Log(EXYNOS_LOG_TRACE
, "SharedMemory map count: %d", map_cnt
);
401 void Exynos_OSAL_SharedMemory_Unmap(OMX_HANDLETYPE handle
, unsigned int ionfd
)
403 EXYNOS_SHARED_MEMORY
*pHandle
= (EXYNOS_SHARED_MEMORY
*)handle
;
404 EXYNOS_SHAREDMEM_LIST
*pSMList
= NULL
;
405 EXYNOS_SHAREDMEM_LIST
*pCurrentElement
= NULL
;
406 EXYNOS_SHAREDMEM_LIST
*pDeleteElement
= NULL
;
411 Exynos_OSAL_MutexLock(pHandle
->hSMMutex
);
412 pSMList
= pHandle
->pAllocMemory
;
413 if (pSMList
== NULL
) {
414 Exynos_OSAL_MutexUnlock(pHandle
->hSMMutex
);
418 pCurrentElement
= pSMList
;
419 if (pSMList
->IONBuffer
== ionfd
) {
420 pDeleteElement
= pSMList
;
421 pHandle
->pAllocMemory
= pSMList
= pSMList
->pNextMemory
;
423 while ((pCurrentElement
!= NULL
) && (((EXYNOS_SHAREDMEM_LIST
*)(pCurrentElement
->pNextMemory
)) != NULL
) &&
424 (((EXYNOS_SHAREDMEM_LIST
*)(pCurrentElement
->pNextMemory
))->IONBuffer
!= ionfd
))
425 pCurrentElement
= pCurrentElement
->pNextMemory
;
427 if ((((EXYNOS_SHAREDMEM_LIST
*)(pCurrentElement
->pNextMemory
)) != NULL
) &&
428 (((EXYNOS_SHAREDMEM_LIST
*)(pCurrentElement
->pNextMemory
))->IONBuffer
== ionfd
)) {
429 pDeleteElement
= pCurrentElement
->pNextMemory
;
430 pCurrentElement
->pNextMemory
= pDeleteElement
->pNextMemory
;
432 Exynos_OSAL_MutexUnlock(pHandle
->hSMMutex
);
433 Exynos_OSAL_Log(EXYNOS_LOG_ERROR
, "Can not find SharedMemory");
437 Exynos_OSAL_MutexUnlock(pHandle
->hSMMutex
);
439 if (munmap(pDeleteElement
->mapAddr
, pDeleteElement
->allocSize
)) {
440 Exynos_OSAL_Log(EXYNOS_LOG_ERROR
, "munmap is failed");
443 pDeleteElement
->mapAddr
= NULL
;
444 pDeleteElement
->allocSize
= 0;
445 pDeleteElement
->IONBuffer
= 0;
447 Exynos_OSAL_Free(pDeleteElement
);
450 Exynos_OSAL_Log(EXYNOS_LOG_TRACE
, "SharedMemory map count: %d", map_cnt
);
457 int Exynos_OSAL_SharedMemory_VirtToION(OMX_HANDLETYPE handle
, OMX_PTR pBuffer
)
459 EXYNOS_SHARED_MEMORY
*pHandle
= (EXYNOS_SHARED_MEMORY
*)handle
;
460 EXYNOS_SHAREDMEM_LIST
*pSMList
= NULL
;
461 EXYNOS_SHAREDMEM_LIST
*pCurrentElement
= NULL
;
462 EXYNOS_SHAREDMEM_LIST
*pFindElement
= NULL
;
464 if (pHandle
== NULL
|| pBuffer
== NULL
)
467 Exynos_OSAL_MutexLock(pHandle
->hSMMutex
);
468 pSMList
= pHandle
->pAllocMemory
;
469 if (pSMList
== NULL
) {
470 Exynos_OSAL_MutexUnlock(pHandle
->hSMMutex
);
474 pCurrentElement
= pSMList
;
475 if (pSMList
->mapAddr
== pBuffer
) {
476 pFindElement
= pSMList
;
478 while ((pCurrentElement
!= NULL
) && (((EXYNOS_SHAREDMEM_LIST
*)(pCurrentElement
->pNextMemory
)) != NULL
) &&
479 (((EXYNOS_SHAREDMEM_LIST
*)(pCurrentElement
->pNextMemory
))->mapAddr
!= pBuffer
))
480 pCurrentElement
= pCurrentElement
->pNextMemory
;
482 if ((((EXYNOS_SHAREDMEM_LIST
*)(pCurrentElement
->pNextMemory
)) != NULL
) &&
483 (((EXYNOS_SHAREDMEM_LIST
*)(pCurrentElement
->pNextMemory
))->mapAddr
== pBuffer
)) {
484 pFindElement
= pCurrentElement
->pNextMemory
;
486 Exynos_OSAL_MutexUnlock(pHandle
->hSMMutex
);
487 Exynos_OSAL_Log(EXYNOS_LOG_WARNING
, "Can not find SharedMemory");
491 Exynos_OSAL_MutexUnlock(pHandle
->hSMMutex
);
493 ion_addr
= pFindElement
->IONBuffer
;
499 OMX_PTR
Exynos_OSAL_SharedMemory_IONToVirt(OMX_HANDLETYPE handle
, int ion_addr
)
501 EXYNOS_SHARED_MEMORY
*pHandle
= (EXYNOS_SHARED_MEMORY
*)handle
;
502 EXYNOS_SHAREDMEM_LIST
*pSMList
= NULL
;
503 EXYNOS_SHAREDMEM_LIST
*pCurrentElement
= NULL
;
504 EXYNOS_SHAREDMEM_LIST
*pFindElement
= NULL
;
505 OMX_PTR pBuffer
= NULL
;
506 if (pHandle
== NULL
|| ion_addr
== 0)
509 Exynos_OSAL_MutexLock(pHandle
->hSMMutex
);
510 pSMList
= pHandle
->pAllocMemory
;
511 if (pSMList
== NULL
) {
512 Exynos_OSAL_MutexUnlock(pHandle
->hSMMutex
);
516 pCurrentElement
= pSMList
;
517 if (pSMList
->IONBuffer
== (OMX_U32
)ion_addr
) {
518 pFindElement
= pSMList
;
520 while ((pCurrentElement
!= NULL
) && (((EXYNOS_SHAREDMEM_LIST
*)(pCurrentElement
->pNextMemory
)) != NULL
) &&
521 (((EXYNOS_SHAREDMEM_LIST
*)(pCurrentElement
->pNextMemory
))->IONBuffer
!= (OMX_U32
)ion_addr
))
522 pCurrentElement
= pCurrentElement
->pNextMemory
;
524 if ((((EXYNOS_SHAREDMEM_LIST
*)(pCurrentElement
->pNextMemory
)) != NULL
) &&
525 (((EXYNOS_SHAREDMEM_LIST
*)(pCurrentElement
->pNextMemory
))->IONBuffer
== (OMX_U32
)ion_addr
)) {
526 pFindElement
= pCurrentElement
->pNextMemory
;
528 Exynos_OSAL_MutexUnlock(pHandle
->hSMMutex
);
529 Exynos_OSAL_Log(EXYNOS_LOG_WARNING
, "Can not find SharedMemory");
533 Exynos_OSAL_MutexUnlock(pHandle
->hSMMutex
);
535 pBuffer
= pFindElement
->mapAddr
;