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