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     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 = 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 
    178     if (IONBuffer <= 0) {
    179         Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_alloc Error: %d", IONBuffer);
    180         Exynos_OSAL_Free((OMX_PTR)pElement);
    181         goto EXIT;
    182     }
    183 
    184     pBuffer = ion_map(IONBuffer, size, 0);
    185     if (pBuffer == MAP_FAILED) {
    186         Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_map Error");
    187         ion_free(IONBuffer);
    188         Exynos_OSAL_Free((OMX_PTR)pElement);
    189         pBuffer = NULL;
    190         goto EXIT;
    191     }
    192 
    193     pElement->IONBuffer = IONBuffer;
    194     pElement->mapAddr = pBuffer;
    195     pElement->allocSize = size;
    196     pElement->pNextMemory = NULL;
    197 
    198     Exynos_OSAL_MutexLock(pHandle->hSMMutex);
    199     pSMList = pHandle->pAllocMemory;
    200     if (pSMList == NULL) {
    201         pHandle->pAllocMemory = pSMList = pElement;
    202     } else {
    203         pCurrentElement = pSMList;
    204         while (pCurrentElement->pNextMemory != NULL) {
    205             pCurrentElement = pCurrentElement->pNextMemory;
    206         }
    207         pCurrentElement->pNextMemory = pElement;
    208     }
    209     Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
    210 
    211     mem_cnt++;
    212     Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SharedMemory alloc count: %d", mem_cnt);
    213 
    214 EXIT:
    215     return pBuffer;
    216 }
    217 
    218 void Exynos_OSAL_SharedMemory_Free(OMX_HANDLETYPE handle, OMX_PTR pBuffer)
    219 {
    220     EXYNOS_SHARED_MEMORY  *pHandle         = (EXYNOS_SHARED_MEMORY *)handle;
    221     EXYNOS_SHAREDMEM_LIST *pSMList         = NULL;
    222     EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL;
    223     EXYNOS_SHAREDMEM_LIST *pDeleteElement  = NULL;
    224 
    225     if (pHandle == NULL)
    226         goto EXIT;
    227 
    228     Exynos_OSAL_MutexLock(pHandle->hSMMutex);
    229     pSMList = pHandle->pAllocMemory;
    230     if (pSMList == NULL) {
    231         Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
    232         goto EXIT;
    233     }
    234 
    235     pCurrentElement = pSMList;
    236     if (pSMList->mapAddr == pBuffer) {
    237         pDeleteElement = pSMList;
    238         pHandle->pAllocMemory = pSMList = pSMList->pNextMemory;
    239     } else {
    240         while ((pCurrentElement != NULL) && (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
    241                (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->mapAddr != pBuffer))
    242             pCurrentElement = pCurrentElement->pNextMemory;
    243 
    244         if ((((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
    245             (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->mapAddr == pBuffer)) {
    246             pDeleteElement = pCurrentElement->pNextMemory;
    247             pCurrentElement->pNextMemory = pDeleteElement->pNextMemory;
    248         } else {
    249             Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
    250             Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Can not find SharedMemory");
    251             goto EXIT;
    252         }
    253     }
    254     Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
    255 
    256     if (ion_unmap(pDeleteElement->mapAddr, pDeleteElement->allocSize)) {
    257         Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_unmap fail");
    258         goto EXIT;
    259     }
    260     pDeleteElement->mapAddr = NULL;
    261     pDeleteElement->allocSize = 0;
    262 
    263     if (pDeleteElement->owner)
    264         ion_free(pDeleteElement->IONBuffer);
    265     pDeleteElement->IONBuffer = 0;
    266 
    267     Exynos_OSAL_Free(pDeleteElement);
    268 
    269     mem_cnt--;
    270     Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SharedMemory free count: %d", mem_cnt);
    271 
    272 EXIT:
    273     return;
    274 }
    275 
    276 OMX_PTR Exynos_OSAL_SharedMemory_Map(OMX_HANDLETYPE handle, OMX_U32 size, unsigned int ionfd)
    277 {
    278     EXYNOS_SHARED_MEMORY  *pHandle = (EXYNOS_SHARED_MEMORY *)handle;
    279     EXYNOS_SHAREDMEM_LIST *pSMList = NULL;
    280     EXYNOS_SHAREDMEM_LIST *pElement = NULL;
    281     EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL;
    282     ion_buffer IONBuffer = 0;
    283     OMX_PTR pBuffer = NULL;
    284 
    285     if (pHandle == NULL)
    286         goto EXIT;
    287 
    288     pElement = (EXYNOS_SHAREDMEM_LIST *)Exynos_OSAL_Malloc(sizeof(EXYNOS_SHAREDMEM_LIST));
    289     Exynos_OSAL_Memset(pElement, 0, sizeof(EXYNOS_SHAREDMEM_LIST));
    290 
    291     IONBuffer = (OMX_PTR)ionfd;
    292 
    293     if (IONBuffer <= 0) {
    294         Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_alloc Error: %d", IONBuffer);
    295         Exynos_OSAL_Free((void*)pElement);
    296         goto EXIT;
    297     }
    298 
    299     pBuffer = ion_map(IONBuffer, size, 0);
    300     if (pBuffer == NULL) {
    301         Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_map Error");
    302         ion_free(IONBuffer);
    303         Exynos_OSAL_Free((void*)pElement);
    304         goto EXIT;
    305     }
    306 
    307     pElement->IONBuffer = IONBuffer;
    308     pElement->mapAddr = pBuffer;
    309     pElement->allocSize = size;
    310     pElement->pNextMemory = NULL;
    311 
    312     Exynos_OSAL_MutexLock(pHandle->hSMMutex);
    313     pSMList = pHandle->pAllocMemory;
    314     if (pSMList == NULL) {
    315         pHandle->pAllocMemory = pSMList = pElement;
    316     } else {
    317         pCurrentElement = pSMList;
    318         while (pCurrentElement->pNextMemory != NULL) {
    319             pCurrentElement = pCurrentElement->pNextMemory;
    320         }
    321         pCurrentElement->pNextMemory = pElement;
    322     }
    323     Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
    324 
    325     mem_cnt++;
    326     Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SharedMemory alloc count: %d", mem_cnt);
    327 
    328 EXIT:
    329     return pBuffer;
    330 }
    331 
    332 void Exynos_OSAL_SharedMemory_Unmap(OMX_HANDLETYPE handle, unsigned int ionfd)
    333 {
    334     EXYNOS_SHARED_MEMORY  *pHandle = (EXYNOS_SHARED_MEMORY *)handle;
    335     EXYNOS_SHAREDMEM_LIST *pSMList = NULL;
    336     EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL;
    337     EXYNOS_SHAREDMEM_LIST *pDeleteElement = NULL;
    338 
    339     if (pHandle == NULL)
    340         goto EXIT;
    341 
    342     Exynos_OSAL_MutexLock(pHandle->hSMMutex);
    343     pSMList = pHandle->pAllocMemory;
    344     if (pSMList == NULL) {
    345         Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
    346         goto EXIT;
    347     }
    348 
    349     pCurrentElement = pSMList;
    350     if (pSMList->IONBuffer == ionfd) {
    351         pDeleteElement = pSMList;
    352         pHandle->pAllocMemory = pSMList = pSMList->pNextMemory;
    353     } else {
    354         while ((pCurrentElement != NULL) && (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
    355                (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->IONBuffer != ionfd))
    356             pCurrentElement = pCurrentElement->pNextMemory;
    357 
    358         if ((((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
    359             (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->IONBuffer == ionfd)) {
    360             pDeleteElement = pCurrentElement->pNextMemory;
    361             pCurrentElement->pNextMemory = pDeleteElement->pNextMemory;
    362         } else {
    363             Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
    364             Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Can not find SharedMemory");
    365             goto EXIT;
    366         }
    367     }
    368     Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
    369 
    370     if (ion_unmap(pDeleteElement->mapAddr, pDeleteElement->allocSize)) {
    371         Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_unmap fail");
    372         goto EXIT;
    373     }
    374     pDeleteElement->mapAddr = NULL;
    375     pDeleteElement->allocSize = 0;
    376     pDeleteElement->IONBuffer = 0;
    377 
    378     Exynos_OSAL_Free(pDeleteElement);
    379 
    380     mem_cnt--;
    381     Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SharedMemory free count: %d", mem_cnt);
    382 
    383 EXIT:
    384     return;
    385 }
    386 
    387 int Exynos_OSAL_SharedMemory_VirtToION(OMX_HANDLETYPE handle, OMX_PTR pBuffer)
    388 {
    389     EXYNOS_SHARED_MEMORY  *pHandle         = (EXYNOS_SHARED_MEMORY *)handle;
    390     EXYNOS_SHAREDMEM_LIST *pSMList         = NULL;
    391     EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL;
    392     EXYNOS_SHAREDMEM_LIST *pFindElement    = NULL;
    393     int ion_addr = 0;
    394     if (pHandle == NULL || pBuffer == NULL)
    395         goto EXIT;
    396 
    397     Exynos_OSAL_MutexLock(pHandle->hSMMutex);
    398     pSMList = pHandle->pAllocMemory;
    399     if (pSMList == NULL) {
    400         Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
    401         goto EXIT;
    402     }
    403 
    404     pCurrentElement = pSMList;
    405     if (pSMList->mapAddr == pBuffer) {
    406         pFindElement = pSMList;
    407     } else {
    408         while ((pCurrentElement != NULL) && (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
    409                (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->mapAddr != pBuffer))
    410             pCurrentElement = pCurrentElement->pNextMemory;
    411 
    412         if ((((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
    413             (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->mapAddr == pBuffer)) {
    414             pFindElement = pCurrentElement->pNextMemory;
    415         } else {
    416             Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
    417             Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "Can not find SharedMemory");
    418             goto EXIT;
    419         }
    420     }
    421     Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
    422 
    423     ion_addr = pFindElement->IONBuffer;
    424 
    425 EXIT:
    426     return ion_addr;
    427 }
    428 
    429 OMX_PTR Exynos_OSAL_SharedMemory_IONToVirt(OMX_HANDLETYPE handle, int ion_addr)
    430 {
    431     EXYNOS_SHARED_MEMORY  *pHandle         = (EXYNOS_SHARED_MEMORY *)handle;
    432     EXYNOS_SHAREDMEM_LIST *pSMList         = NULL;
    433     EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL;
    434     EXYNOS_SHAREDMEM_LIST *pFindElement    = NULL;
    435     OMX_PTR pBuffer = NULL;
    436     if (pHandle == NULL || ion_addr == 0)
    437         goto EXIT;
    438 
    439     Exynos_OSAL_MutexLock(pHandle->hSMMutex);
    440     pSMList = pHandle->pAllocMemory;
    441     if (pSMList == NULL) {
    442         Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
    443         goto EXIT;
    444     }
    445 
    446     pCurrentElement = pSMList;
    447     if (pSMList->IONBuffer == ion_addr) {
    448         pFindElement = pSMList;
    449     } else {
    450         while ((pCurrentElement != NULL) && (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
    451                (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->IONBuffer != ion_addr))
    452             pCurrentElement = pCurrentElement->pNextMemory;
    453 
    454         if ((((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
    455             (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->IONBuffer == ion_addr)) {
    456             pFindElement = pCurrentElement->pNextMemory;
    457         } else {
    458             Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
    459             Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "Can not find SharedMemory");
    460             goto EXIT;
    461         }
    462     }
    463     Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
    464 
    465     pBuffer = pFindElement->mapAddr;
    466 
    467 EXIT:
    468     return pBuffer;
    469 }
    470