1 /* 2 * Copyright (C) 2016 ARM Limited. All rights reserved. 3 * 4 * Copyright (C) 2008 The Android Open Source Project 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * You may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 #include <hardware/hardware.h> 20 21 #if GRALLOC_USE_GRALLOC1_API == 1 22 #include <hardware/gralloc1.h> 23 #else 24 #include <hardware/gralloc.h> 25 #endif 26 27 #include "mali_gralloc_module.h" 28 #include "mali_gralloc_private_interface_types.h" 29 #include "mali_gralloc_buffer.h" 30 #include "mali_gralloc_ion.h" 31 #include "gralloc_buffer_priv.h" 32 #include "mali_gralloc_bufferallocation.h" 33 #include "mali_gralloc_debug.h" 34 35 static pthread_mutex_t s_map_lock = PTHREAD_MUTEX_INITIALIZER; 36 37 int mali_gralloc_reference_retain(mali_gralloc_module const *module, buffer_handle_t handle) 38 { 39 GRALLOC_UNUSED(module); 40 41 if (private_handle_t::validate(handle) < 0) 42 { 43 AERR("Registering/Retaining invalid buffer %p, returning error", handle); 44 return -EINVAL; 45 } 46 47 private_handle_t *hnd = (private_handle_t *)handle; 48 pthread_mutex_lock(&s_map_lock); 49 50 if (hnd->allocating_pid == getpid() || hnd->remote_pid == getpid()) 51 { 52 hnd->ref_count++; 53 pthread_mutex_unlock(&s_map_lock); 54 return 0; 55 } 56 else 57 { 58 hnd->remote_pid = getpid(); 59 hnd->ref_count = 1; 60 } 61 62 int retval = -EINVAL; 63 64 if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) 65 { 66 retval = 0; 67 } 68 else if (hnd->flags & (private_handle_t::PRIV_FLAGS_USES_ION)) 69 { 70 retval = mali_gralloc_ion_map(hnd); 71 } 72 else 73 { 74 AERR("unkown buffer flags not supported. flags = %d", hnd->flags); 75 } 76 77 pthread_mutex_unlock(&s_map_lock); 78 return retval; 79 } 80 81 int mali_gralloc_reference_release(mali_gralloc_module const *module, buffer_handle_t handle, bool canFree) 82 { 83 GRALLOC_UNUSED(module); 84 85 if (private_handle_t::validate(handle) < 0) 86 { 87 AERR("unregistering/releasing invalid buffer %p, returning error", handle); 88 return -EINVAL; 89 } 90 91 private_handle_t *hnd = (private_handle_t *)handle; 92 pthread_mutex_lock(&s_map_lock); 93 94 if (hnd->ref_count == 0) 95 { 96 AERR("Buffer %p should have already been released", handle); 97 pthread_mutex_unlock(&s_map_lock); 98 return -EINVAL; 99 } 100 101 if (hnd->allocating_pid == getpid()) 102 { 103 hnd->ref_count--; 104 105 if (hnd->ref_count == 0 && canFree) 106 { 107 108 if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) 109 { 110 close(hnd->fd); 111 } 112 else 113 { 114 mali_gralloc_dump_buffer_erase(hnd); 115 } 116 mali_gralloc_buffer_free(handle); 117 delete handle; 118 119 } 120 } 121 else if (hnd->remote_pid == getpid()) // never unmap buffers that were not imported into this process 122 { 123 hnd->ref_count--; 124 125 if (hnd->ref_count == 0) 126 { 127 128 if (hnd->flags & (private_handle_t::PRIV_FLAGS_USES_ION)) 129 { 130 mali_gralloc_ion_unmap(hnd); 131 } 132 else 133 { 134 AERR("Unregistering/Releasing unknown buffer is not supported. Flags = %d", hnd->flags); 135 } 136 137 /* 138 * Close shared attribute region file descriptor. It might seem strange to "free" 139 * this here since this can happen in a client process, but free here is nothing 140 * but unmapping and closing the duplicated file descriptor. The original ashmem 141 * fd instance is still open until alloc_device_free() is called. Even sharing 142 * of gralloc buffers within the same process should have fds dup:ed. 143 */ 144 gralloc_buffer_attr_free(hnd); 145 146 hnd->base = 0; 147 hnd->writeOwner = 0; 148 } 149 } 150 else 151 { 152 AERR("Trying to unregister buffer %p from process %d that was not imported into current process: %d", hnd, 153 hnd->remote_pid, getpid()); 154 } 155 156 pthread_mutex_unlock(&s_map_lock); 157 return 0; 158 } 159