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