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