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