1 /*
2 * Copyright (C) 2016, 2018-2020 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/gralloc1.h>
20
21 #include "mali_gralloc_buffer.h"
22 #include "allocator/mali_gralloc_ion.h"
23 #include "allocator/mali_gralloc_shared_memory.h"
24 #include "mali_gralloc_bufferallocation.h"
25 #include "mali_gralloc_debug.h"
26 #include "mali_gralloc_reference.h"
27 #include "mali_gralloc_usages.h"
28
29 static pthread_mutex_t s_map_lock = PTHREAD_MUTEX_INITIALIZER;
30
mali_gralloc_reference_retain(buffer_handle_t handle)31 int mali_gralloc_reference_retain(buffer_handle_t handle)
32 {
33 if (private_handle_t::validate(handle) < 0)
34 {
35 MALI_GRALLOC_LOGE("Registering/Retaining invalid buffer %p, returning error", handle);
36 return -EINVAL;
37 }
38
39 private_handle_t *hnd = (private_handle_t *)handle;
40 pthread_mutex_lock(&s_map_lock);
41 int retval = 0;
42
43 if (hnd->allocating_pid == getpid() || hnd->remote_pid == getpid())
44 {
45 hnd->ref_count++;
46 }
47 else
48 {
49 hnd->remote_pid = getpid();
50 hnd->ref_count = 1;
51
52 // Reset the handle bases, this is used to check if a buffer is mapped
53 for (int fidx = 0; fidx < hnd->fd_count; fidx++) {
54 hnd->bases[fidx] = 0;
55 }
56 }
57
58 pthread_mutex_unlock(&s_map_lock);
59
60 // TODO(b/187145254): CPU_READ/WRITE buffer is not being properly locked from
61 // MFC. This is a WA for the time being.
62 constexpr auto cpu_access_usage = (
63 GRALLOC_USAGE_SW_WRITE_OFTEN |
64 GRALLOC_USAGE_SW_READ_OFTEN |
65 GRALLOC_USAGE_SW_WRITE_RARELY |
66 GRALLOC_USAGE_SW_READ_RARELY
67 );
68
69 if (hnd->get_usage() & cpu_access_usage)
70 retval = mali_gralloc_reference_map(handle);
71
72 return retval;
73 }
74
mali_gralloc_reference_map(buffer_handle_t handle)75 int mali_gralloc_reference_map(buffer_handle_t handle) {
76 private_handle_t *hnd = (private_handle_t *)handle;
77
78 pthread_mutex_lock(&s_map_lock);
79
80 if (hnd->bases[0]) {
81 MALI_GRALLOC_LOGV("Buffer is already mapped");
82 pthread_mutex_unlock(&s_map_lock);
83 return 0;
84 }
85
86 int retval = mali_gralloc_ion_map(hnd);
87
88 pthread_mutex_unlock(&s_map_lock);
89
90 return retval;
91 }
92
mali_gralloc_reference_release(buffer_handle_t handle,bool canFree)93 int mali_gralloc_reference_release(buffer_handle_t handle, bool canFree)
94 {
95 if (private_handle_t::validate(handle) < 0)
96 {
97 MALI_GRALLOC_LOGE("unregistering/releasing invalid buffer %p, returning error", handle);
98 return -EINVAL;
99 }
100
101 private_handle_t *hnd = (private_handle_t *)handle;
102 pthread_mutex_lock(&s_map_lock);
103
104 if (hnd->ref_count == 0)
105 {
106 MALI_GRALLOC_LOGE("Buffer %p should have already been released", handle);
107 pthread_mutex_unlock(&s_map_lock);
108 return -EINVAL;
109 }
110
111 if (hnd->allocating_pid == getpid())
112 {
113 hnd->ref_count--;
114
115 if (hnd->ref_count == 0 && canFree)
116 {
117 mali_gralloc_dump_buffer_erase(hnd);
118 mali_gralloc_buffer_free(handle);
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 mali_gralloc_ion_unmap(hnd);
128
129 /* TODO: Make this unmapping of shared meta fd into a function? */
130 if (hnd->attr_base)
131 {
132 munmap(hnd->attr_base, hnd->attr_size);
133 hnd->attr_base = nullptr;
134 }
135 }
136 }
137 else
138 {
139 MALI_GRALLOC_LOGE("Trying to unregister buffer %p from process %d that was not imported into current process: %d", hnd,
140 hnd->remote_pid, getpid());
141 }
142
143 pthread_mutex_unlock(&s_map_lock);
144 return 0;
145 }
146
mali_gralloc_reference_validate(buffer_handle_t handle)147 int mali_gralloc_reference_validate(buffer_handle_t handle)
148 {
149 if (private_handle_t::validate(handle) < 0)
150 {
151 MALI_GRALLOC_LOGE("Reference invalid buffer %p, returning error", handle);
152 return -EINVAL;
153 }
154
155 const auto *hnd = (private_handle_t *)handle;
156 pthread_mutex_lock(&s_map_lock);
157
158 if (hnd->allocating_pid == getpid() || hnd->remote_pid == getpid()) {
159 pthread_mutex_unlock(&s_map_lock);
160 return 0;
161 } else {
162 pthread_mutex_unlock(&s_map_lock);
163 MALI_GRALLOC_LOGE("Reference unimported buffer %p, returning error", handle);
164 return -EINVAL;
165 }
166 }
167
168