dff3cfaaea979c06736d30a6efea39a7f959b4db
[platform/adaptation/ap_samsung/libomxil-e3250-v4l2.git] / openmax / osal / Exynos_OSAL_SharedMemory.c
1 /*
2  *
3  * Copyright 2012 Samsung Electronics S.LSI Co. LTD
4  *
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
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17
18 /*
19  * @file        Exynos_OSAL_SharedMemory.c
20  * @brief
21  * @author      SeungBeom Kim (sbcrux.kim@samsung.com)
22  *              Taehwan Kim (t_h.kim@samsung.com)
23  * @version     2.0.0
24  * @history
25  *   2012.02.20 : Create
26  */
27
28 #include <stdbool.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <errno.h>
33 #include <pthread.h>
34 #ifndef TIZEN_FEATURE_E3250 /* build env */
35 #include <cutils/log.h>
36 #include <cutils/atomic.h>
37 #endif
38 #include <fcntl.h>
39 #include <sys/mman.h>
40
41 #include "Exynos_OSAL_Memory.h"
42 #include "Exynos_OSAL_SharedMemory.h"
43 #include "Exynos_OSAL_Mutex.h"
44 #include "ion.h"
45
46 #define EXYNOS_LOG_OFF
47 #include "Exynos_OSAL_Log.h"
48
49 static int mem_cnt = 0;
50
51 struct EXYNOS_SHAREDMEM_LIST;
52 typedef struct _EXYNOS_SHAREDMEM_LIST
53 {
54     OMX_U32                        IONBuffer;
55     OMX_PTR                        mapAddr;
56     OMX_U32                        allocSize;
57     bool                           owner;
58     struct _EXYNOS_SHAREDMEM_LIST *pNextMemory;
59 } EXYNOS_SHAREDMEM_LIST;
60
61 typedef struct _EXYNOS_SHARED_MEMORY
62 {
63     OMX_HANDLETYPE         hIONHandle;
64     EXYNOS_SHAREDMEM_LIST *pAllocMemory;
65     OMX_HANDLETYPE         hSMMutex;
66 } EXYNOS_SHARED_MEMORY;
67
68
69 OMX_HANDLETYPE Exynos_OSAL_SharedMemory_Open()
70 {
71     EXYNOS_SHARED_MEMORY *pHandle = NULL;
72     ion_client            IONClient = 0;
73
74     pHandle = (EXYNOS_SHARED_MEMORY *)Exynos_OSAL_Malloc(sizeof(EXYNOS_SHARED_MEMORY));
75     Exynos_OSAL_Memset(pHandle, 0, sizeof(EXYNOS_SHARED_MEMORY));
76     if (pHandle == NULL)
77         goto EXIT;
78
79     IONClient = (OMX_HANDLETYPE)ion_client_create();
80     if (IONClient <= 0) {
81         Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_client_create Error: %d", IONClient);
82         Exynos_OSAL_Free((void *)pHandle);
83         pHandle = NULL;
84         goto EXIT;
85     }
86
87     pHandle->hIONHandle = IONClient;
88
89     Exynos_OSAL_MutexCreate(&pHandle->hSMMutex);
90
91 EXIT:
92     return (OMX_HANDLETYPE)pHandle;
93 }
94
95 void Exynos_OSAL_SharedMemory_Close(OMX_HANDLETYPE handle)
96 {
97     EXYNOS_SHARED_MEMORY *pHandle = (EXYNOS_SHARED_MEMORY *)handle;
98     EXYNOS_SHAREDMEM_LIST *pSMList = NULL;
99     EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL;
100     EXYNOS_SHAREDMEM_LIST *pDeleteElement = NULL;
101
102     if (pHandle == NULL)
103         goto EXIT;
104
105     Exynos_OSAL_MutexLock(pHandle->hSMMutex);
106     pCurrentElement = pSMList = pHandle->pAllocMemory;
107
108     while (pCurrentElement != NULL) {
109         pDeleteElement = pCurrentElement;
110         pCurrentElement = pCurrentElement->pNextMemory;
111
112         if (ion_unmap(pDeleteElement->mapAddr, pDeleteElement->allocSize))
113             Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_unmap fail");
114
115         pDeleteElement->mapAddr = NULL;
116         pDeleteElement->allocSize = 0;
117
118         if (pDeleteElement->owner)
119             ion_free(pDeleteElement->IONBuffer);
120         pDeleteElement->IONBuffer = 0;
121
122         Exynos_OSAL_Free(pDeleteElement);
123
124         mem_cnt--;
125         Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SharedMemory free count: %d", mem_cnt);
126     }
127
128     pHandle->pAllocMemory = pSMList = NULL;
129     Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
130
131     Exynos_OSAL_MutexTerminate(pHandle->hSMMutex);
132     pHandle->hSMMutex = NULL;
133
134     ion_client_destroy((ion_client)pHandle->hIONHandle);
135     pHandle->hIONHandle = NULL;
136
137     Exynos_OSAL_Free(pHandle);
138
139 EXIT:
140     return;
141 }
142
143 OMX_PTR Exynos_OSAL_SharedMemory_Alloc(OMX_HANDLETYPE handle, OMX_U32 size, MEMORY_TYPE memoryType)
144 {
145     EXYNOS_SHARED_MEMORY  *pHandle         = (EXYNOS_SHARED_MEMORY *)handle;
146     EXYNOS_SHAREDMEM_LIST *pSMList         = NULL;
147     EXYNOS_SHAREDMEM_LIST *pElement        = NULL;
148     EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL;
149     ion_buffer             IONBuffer       = 0;
150     OMX_PTR                pBuffer         = NULL;
151     unsigned int mask;
152     unsigned int flag;
153
154     if (pHandle == NULL)
155         goto EXIT;
156
157     pElement = (EXYNOS_SHAREDMEM_LIST *)Exynos_OSAL_Malloc(sizeof(EXYNOS_SHAREDMEM_LIST));
158     Exynos_OSAL_Memset(pElement, 0, sizeof(EXYNOS_SHAREDMEM_LIST));
159     pElement->owner = true;
160
161     switch (memoryType) {
162     case SECURE_MEMORY:
163         mask = ION_HEAP_EXYNOS_CONTIG_MASK;
164         flag = ION_EXYNOS_FIMD_VIDEO_MASK;
165         break;
166     case NORMAL_MEMORY:
167         mask = ION_HEAP_EXYNOS_MASK;
168         flag = 0;
169         break;
170     case SYSTEM_MEMORY:
171         mask = ION_HEAP_SYSTEM_MASK;
172         flag = ION_FLAG_CACHED;
173         break;
174     default:
175         pBuffer = NULL;
176         goto EXIT;
177         break;
178     }
179
180     IONBuffer = ion_alloc((ion_client)pHandle->hIONHandle, size, 0, mask, flag);
181
182     if (IONBuffer <= 0) {
183         Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_alloc Error: %d", IONBuffer);
184         Exynos_OSAL_Free((OMX_PTR)pElement);
185         goto EXIT;
186     }
187
188     pBuffer = ion_map(IONBuffer, size, 0);
189     if (pBuffer == MAP_FAILED) {
190         Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_map Error");
191         ion_free(IONBuffer);
192         Exynos_OSAL_Free((OMX_PTR)pElement);
193         pBuffer = NULL;
194         goto EXIT;
195     }
196
197     pElement->IONBuffer = IONBuffer;
198     pElement->mapAddr = pBuffer;
199     pElement->allocSize = size;
200     pElement->pNextMemory = NULL;
201
202     Exynos_OSAL_MutexLock(pHandle->hSMMutex);
203     pSMList = pHandle->pAllocMemory;
204     if (pSMList == NULL) {
205         pHandle->pAllocMemory = pSMList = pElement;
206     } else {
207         pCurrentElement = pSMList;
208         while (pCurrentElement->pNextMemory != NULL) {
209             pCurrentElement = pCurrentElement->pNextMemory;
210         }
211         pCurrentElement->pNextMemory = pElement;
212     }
213     Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
214
215     mem_cnt++;
216 #ifndef TIZEN_FEATURE_E3250
217     Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SharedMemory alloc count: %d", mem_cnt);
218 #else
219     Exynos_OSAL_Log(EXYNOS_LOG_VERVOSE, "SharedMemory alloc count: %d", mem_cnt);
220 #endif
221
222 EXIT:
223     return pBuffer;
224 }
225
226 void Exynos_OSAL_SharedMemory_Free(OMX_HANDLETYPE handle, OMX_PTR pBuffer)
227 {
228     EXYNOS_SHARED_MEMORY  *pHandle         = (EXYNOS_SHARED_MEMORY *)handle;
229     EXYNOS_SHAREDMEM_LIST *pSMList         = NULL;
230     EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL;
231     EXYNOS_SHAREDMEM_LIST *pDeleteElement  = NULL;
232
233     if (pHandle == NULL)
234         goto EXIT;
235
236     Exynos_OSAL_MutexLock(pHandle->hSMMutex);
237     pSMList = pHandle->pAllocMemory;
238     if (pSMList == NULL) {
239         Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
240         goto EXIT;
241     }
242
243     pCurrentElement = pSMList;
244     if (pSMList->mapAddr == pBuffer) {
245         pDeleteElement = pSMList;
246         pHandle->pAllocMemory = pSMList = pSMList->pNextMemory;
247     } else {
248         while ((pCurrentElement != NULL) && (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
249                (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->mapAddr != pBuffer))
250             pCurrentElement = pCurrentElement->pNextMemory;
251
252         if ((((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
253             (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->mapAddr == pBuffer)) {
254             pDeleteElement = pCurrentElement->pNextMemory;
255             pCurrentElement->pNextMemory = pDeleteElement->pNextMemory;
256         } else {
257             Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
258             Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Can not find SharedMemory");
259             goto EXIT;
260         }
261     }
262     Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
263
264     if (ion_unmap(pDeleteElement->mapAddr, pDeleteElement->allocSize)) {
265         Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_unmap fail");
266         goto EXIT;
267     }
268     pDeleteElement->mapAddr = NULL;
269     pDeleteElement->allocSize = 0;
270
271     if (pDeleteElement->owner)
272         ion_free(pDeleteElement->IONBuffer);
273     pDeleteElement->IONBuffer = 0;
274
275     Exynos_OSAL_Free(pDeleteElement);
276
277     mem_cnt--;
278 #ifndef TIZEN_FEATURE_E3250
279     Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SharedMemory free count: %d", mem_cnt);
280 #else
281     Exynos_OSAL_Log(EXYNOS_LOG_VERVOSE, "SharedMemory free count: %d", mem_cnt);
282 #endif
283
284 EXIT:
285     return;
286 }
287
288 #ifdef USE_DMA_BUF
289 OMX_PTR Exynos_OSAL_SharedMemory_Map(OMX_HANDLETYPE handle, OMX_U32 size, unsigned int ionfd)
290 {
291     EXYNOS_SHARED_MEMORY  *pHandle = (EXYNOS_SHARED_MEMORY *)handle;
292     EXYNOS_SHAREDMEM_LIST *pSMList = NULL;
293     EXYNOS_SHAREDMEM_LIST *pElement = NULL;
294     EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL;
295     ion_buffer IONBuffer = 0;
296     OMX_PTR pBuffer = NULL;
297
298     if (pHandle == NULL)
299         goto EXIT;
300
301     pElement = (EXYNOS_SHAREDMEM_LIST *)Exynos_OSAL_Malloc(sizeof(EXYNOS_SHAREDMEM_LIST));
302     Exynos_OSAL_Memset(pElement, 0, sizeof(EXYNOS_SHAREDMEM_LIST));
303
304     IONBuffer = (OMX_PTR)ionfd;
305
306     if (IONBuffer <= 0) {
307         Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_alloc Error: %d", IONBuffer);
308         Exynos_OSAL_Free((void*)pElement);
309         goto EXIT;
310     }
311
312     pBuffer = ion_map(IONBuffer, size, 0);
313     if (pBuffer == NULL) {
314         Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_map Error");
315         ion_free(IONBuffer);
316         Exynos_OSAL_Free((void*)pElement);
317         goto EXIT;
318     }
319
320     pElement->IONBuffer = IONBuffer;
321     pElement->mapAddr = pBuffer;
322     pElement->allocSize = size;
323     pElement->pNextMemory = NULL;
324
325     Exynos_OSAL_MutexLock(pHandle->hSMMutex);
326     pSMList = pHandle->pAllocMemory;
327     if (pSMList == NULL) {
328         pHandle->pAllocMemory = pSMList = pElement;
329     } else {
330         pCurrentElement = pSMList;
331         while (pCurrentElement->pNextMemory != NULL) {
332             pCurrentElement = pCurrentElement->pNextMemory;
333         }
334         pCurrentElement->pNextMemory = pElement;
335     }
336     Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
337
338     mem_cnt++;
339 #ifndef TIZEN_FEATURE_E3250
340     Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SharedMemory alloc count: %d", mem_cnt);
341 #else
342     Exynos_OSAL_Log(EXYNOS_LOG_VERVOSE, "SharedMemory alloc count: %d", mem_cnt);
343 #endif
344
345 EXIT:
346     return pBuffer;
347 }
348
349 void Exynos_OSAL_SharedMemory_Unmap(OMX_HANDLETYPE handle, unsigned int ionfd)
350 {
351     EXYNOS_SHARED_MEMORY  *pHandle = (EXYNOS_SHARED_MEMORY *)handle;
352     EXYNOS_SHAREDMEM_LIST *pSMList = NULL;
353     EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL;
354     EXYNOS_SHAREDMEM_LIST *pDeleteElement = NULL;
355
356     if (pHandle == NULL)
357         goto EXIT;
358
359     Exynos_OSAL_MutexLock(pHandle->hSMMutex);
360     pSMList = pHandle->pAllocMemory;
361     if (pSMList == NULL) {
362         Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
363         goto EXIT;
364     }
365
366     pCurrentElement = pSMList;
367     if (pSMList->IONBuffer == ionfd) {
368         pDeleteElement = pSMList;
369         pHandle->pAllocMemory = pSMList = pSMList->pNextMemory;
370     } else {
371         while ((pCurrentElement != NULL) && (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
372                (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->IONBuffer != ionfd))
373             pCurrentElement = pCurrentElement->pNextMemory;
374
375         if ((((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
376             (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->IONBuffer == ionfd)) {
377             pDeleteElement = pCurrentElement->pNextMemory;
378             pCurrentElement->pNextMemory = pDeleteElement->pNextMemory;
379         } else {
380             Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
381             Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Can not find SharedMemory");
382             goto EXIT;
383         }
384     }
385     Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
386
387     if (ion_unmap(pDeleteElement->mapAddr, pDeleteElement->allocSize)) {
388         Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_unmap fail");
389         goto EXIT;
390     }
391     pDeleteElement->mapAddr = NULL;
392     pDeleteElement->allocSize = 0;
393     pDeleteElement->IONBuffer = 0;
394
395     Exynos_OSAL_Free(pDeleteElement);
396
397     mem_cnt--;
398 #ifndef TIZEN_FEATURE_E3250
399     Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SharedMemory free count: %d", mem_cnt);
400 #else
401     Exynos_OSAL_Log(EXYNOS_LOG_VERVOSE, "SharedMemory free count: %d", mem_cnt);
402 #endif
403
404 EXIT:
405     return;
406 }
407 #endif
408
409 int Exynos_OSAL_SharedMemory_VirtToION(OMX_HANDLETYPE handle, OMX_PTR pBuffer)
410 {
411     EXYNOS_SHARED_MEMORY  *pHandle         = (EXYNOS_SHARED_MEMORY *)handle;
412     EXYNOS_SHAREDMEM_LIST *pSMList         = NULL;
413     EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL;
414     EXYNOS_SHAREDMEM_LIST *pFindElement    = NULL;
415     int ion_addr = 0;
416     if (pHandle == NULL || pBuffer == NULL)
417         goto EXIT;
418
419     Exynos_OSAL_MutexLock(pHandle->hSMMutex);
420     pSMList = pHandle->pAllocMemory;
421     if (pSMList == NULL) {
422         Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
423         goto EXIT;
424     }
425
426     pCurrentElement = pSMList;
427     if (pSMList->mapAddr == pBuffer) {
428         pFindElement = pSMList;
429     } else {
430         while ((pCurrentElement != NULL) && (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
431                (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->mapAddr != pBuffer))
432             pCurrentElement = pCurrentElement->pNextMemory;
433
434         if ((((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
435             (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->mapAddr == pBuffer)) {
436             pFindElement = pCurrentElement->pNextMemory;
437         } else {
438             Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
439             Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Can not find SharedMemory");
440             goto EXIT;
441         }
442     }
443     Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
444
445     ion_addr = pFindElement->IONBuffer;
446
447 EXIT:
448     return ion_addr;
449 }
450
451 OMX_PTR Exynos_OSAL_SharedMemory_IONToVirt(OMX_HANDLETYPE handle, int ion_addr)
452 {
453     EXYNOS_SHARED_MEMORY  *pHandle         = (EXYNOS_SHARED_MEMORY *)handle;
454     EXYNOS_SHAREDMEM_LIST *pSMList         = NULL;
455     EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL;
456     EXYNOS_SHAREDMEM_LIST *pFindElement    = NULL;
457     OMX_PTR pBuffer = NULL;
458     if (pHandle == NULL || ion_addr == 0)
459         goto EXIT;
460
461     Exynos_OSAL_MutexLock(pHandle->hSMMutex);
462     pSMList = pHandle->pAllocMemory;
463     if (pSMList == NULL) {
464         Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
465         goto EXIT;
466     }
467
468     pCurrentElement = pSMList;
469     if (pSMList->IONBuffer == ion_addr) {
470         pFindElement = pSMList;
471     } else {
472         while ((pCurrentElement != NULL) && (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
473                (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->IONBuffer != ion_addr))
474             pCurrentElement = pCurrentElement->pNextMemory;
475
476         if ((((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
477             (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->IONBuffer == ion_addr)) {
478             pFindElement = pCurrentElement->pNextMemory;
479         } else {
480             Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
481             Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Can not find SharedMemory");
482             goto EXIT;
483         }
484     }
485     Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
486
487     pBuffer = pFindElement->mapAddr;
488
489 EXIT:
490     return pBuffer;
491 }