1 /* 2 * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. 3 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above 10 * copyright notice, this list of conditions and the following 11 * disclaimer in the documentation and/or other materials provided 12 * with the distribution. 13 * * Neither the name of The Linux Foundation nor the names of its 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <cutils/log.h> 31 #include <cutils/native_handle.h> 32 #include <gralloc_priv.h> 33 #ifdef USE_GENLOCK 34 #include <linux/genlock.h> 35 #endif 36 #include <fcntl.h> 37 #include <sys/ioctl.h> 38 39 #include "genlock.h" 40 41 #define GENLOCK_DEVICE "/dev/genlock" 42 43 44 45 #ifdef USE_GENLOCK 46 47 namespace { 48 /* Internal function to map the userspace locks to the kernel lock types */ 49 int get_kernel_lock_type(genlock_lock_type lockType) 50 { 51 int kLockType = 0; 52 // If the user sets both a read and write lock, higher preference is 53 // given to the write lock. 54 if (lockType & GENLOCK_WRITE_LOCK) { 55 kLockType = GENLOCK_WRLOCK; 56 } else if (lockType & GENLOCK_READ_LOCK) { 57 kLockType = GENLOCK_RDLOCK; 58 } else { 59 ALOGE("%s: invalid lockType (lockType = %d)", 60 __FUNCTION__, lockType); 61 return -1; 62 } 63 return kLockType; 64 } 65 66 /* Internal function to perform the actual lock/unlock operations */ 67 genlock_status_t perform_lock_unlock_operation(native_handle_t *buffer_handle, 68 int lockType, int timeout, 69 int flags) 70 { 71 if (private_handle_t::validate(buffer_handle)) { 72 ALOGE("%s: handle is invalid", __FUNCTION__); 73 return GENLOCK_FAILURE; 74 } 75 76 private_handle_t *hnd = reinterpret_cast<private_handle_t*> 77 (buffer_handle); 78 if ((hnd->flags & private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED) == 0) { 79 if (hnd->genlockPrivFd < 0) { 80 ALOGE("%s: the lock has not been created," 81 "or has not been attached", __FUNCTION__); 82 return GENLOCK_FAILURE; 83 } 84 85 genlock_lock lock; 86 lock.op = lockType; 87 lock.flags = flags; 88 lock.timeout = timeout; 89 lock.fd = hnd->genlockHandle; 90 91 #ifdef GENLOCK_IOC_DREADLOCK 92 if (ioctl(hnd->genlockPrivFd, GENLOCK_IOC_DREADLOCK, &lock)) { 93 ALOGE("%s: GENLOCK_IOC_DREADLOCK failed (lockType0x%x," 94 "err=%s fd=%d)", __FUNCTION__, 95 lockType, strerror(errno), hnd->fd); 96 if (ETIMEDOUT == errno) 97 return GENLOCK_TIMEDOUT; 98 99 return GENLOCK_FAILURE; 100 } 101 #else 102 // depreciated 103 if (ioctl(hnd->genlockPrivFd, GENLOCK_IOC_LOCK, &lock)) { 104 ALOGE("%s: GENLOCK_IOC_LOCK failed (lockType0x%x, err=%s fd=%d)" 105 ,__FUNCTION__, lockType, strerror(errno), hnd->fd); 106 if (ETIMEDOUT == errno) 107 return GENLOCK_TIMEDOUT; 108 109 return GENLOCK_FAILURE; 110 } 111 #endif 112 } 113 return GENLOCK_NO_ERROR; 114 } 115 116 /* Internal function to close the fd and release the handle */ 117 void close_genlock_fd_and_handle(int& fd, int& handle) 118 { 119 if (fd >=0 ) { 120 close(fd); 121 fd = -1; 122 } 123 124 if (handle >= 0) { 125 close(handle); 126 handle = -1; 127 } 128 } 129 } 130 131 #endif // USE_GENLOCK 132 133 134 135 /* 136 * Create a genlock lock. The genlock lock file descriptor and the lock 137 * handle are stored in the buffer_handle. 138 * 139 * @param: handle of the buffer 140 * @return error status. 141 */ 142 genlock_status_t genlock_create_lock(native_handle_t *buffer_handle) 143 { 144 genlock_status_t ret = GENLOCK_NO_ERROR; 145 #ifdef USE_GENLOCK 146 if (private_handle_t::validate(buffer_handle)) { 147 ALOGE("%s: handle is invalid", __FUNCTION__); 148 return GENLOCK_FAILURE; 149 } 150 151 private_handle_t *hnd = reinterpret_cast<private_handle_t*>(buffer_handle); 152 if ((hnd->flags & private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED) == 0) { 153 // Open the genlock device 154 int fd = open(GENLOCK_DEVICE, O_RDWR); 155 if (fd < 0) { 156 ALOGE("%s: open genlock device failed (err=%s)", __FUNCTION__, 157 strerror(errno)); 158 return GENLOCK_FAILURE; 159 } 160 161 // Create a new lock 162 genlock_lock lock; 163 if (ioctl(fd, GENLOCK_IOC_NEW, NULL)) { 164 ALOGE("%s: GENLOCK_IOC_NEW failed (error=%s)", __FUNCTION__, 165 strerror(errno)); 166 close_genlock_fd_and_handle(fd, lock.fd); 167 ret = GENLOCK_FAILURE; 168 } 169 170 // Export the lock for other processes to be able to use it. 171 if (GENLOCK_FAILURE != ret) { 172 if (ioctl(fd, GENLOCK_IOC_EXPORT, &lock)) { 173 ALOGE("%s: GENLOCK_IOC_EXPORT failed (error=%s)", __FUNCTION__, 174 strerror(errno)); 175 close_genlock_fd_and_handle(fd, lock.fd); 176 ret = GENLOCK_FAILURE; 177 } 178 } 179 180 // Store the lock params in the handle. 181 hnd->genlockPrivFd = fd; 182 hnd->genlockHandle = lock.fd; 183 } else { 184 hnd->genlockHandle = 0; 185 } 186 #endif 187 return ret; 188 } 189 190 191 /* 192 * Release a genlock lock associated with the handle. 193 * 194 * @param: handle of the buffer 195 * @return error status. 196 */ 197 genlock_status_t genlock_release_lock(native_handle_t *buffer_handle) 198 { 199 genlock_status_t ret = GENLOCK_NO_ERROR; 200 #ifdef USE_GENLOCK 201 if (private_handle_t::validate(buffer_handle)) { 202 ALOGE("%s: handle is invalid", __FUNCTION__); 203 return GENLOCK_FAILURE; 204 } 205 206 private_handle_t *hnd = reinterpret_cast<private_handle_t*>(buffer_handle); 207 if ((hnd->flags & private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED) == 0) { 208 if (hnd->genlockPrivFd < 0) { 209 ALOGE("%s: the lock is invalid", __FUNCTION__); 210 return GENLOCK_FAILURE; 211 } 212 213 // Close the fd and reset the parameters. 214 close_genlock_fd_and_handle(hnd->genlockPrivFd, hnd->genlockHandle); 215 } 216 #endif 217 return ret; 218 } 219 220 221 /* 222 * Attach a lock to the buffer handle passed via an IPC. 223 * 224 * @param: handle of the buffer 225 * @return error status. 226 */ 227 genlock_status_t genlock_attach_lock(native_handle_t *buffer_handle) 228 { 229 genlock_status_t ret = GENLOCK_NO_ERROR; 230 #ifdef USE_GENLOCK 231 if (private_handle_t::validate(buffer_handle)) { 232 ALOGE("%s: handle is invalid", __FUNCTION__); 233 return GENLOCK_FAILURE; 234 } 235 236 private_handle_t *hnd = reinterpret_cast<private_handle_t*>(buffer_handle); 237 if ((hnd->flags & private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED) == 0) { 238 // Open the genlock device 239 int fd = open(GENLOCK_DEVICE, O_RDWR); 240 if (fd < 0) { 241 ALOGE("%s: open genlock device failed (err=%s)", __FUNCTION__, 242 strerror(errno)); 243 return GENLOCK_FAILURE; 244 } 245 246 // Attach the local handle to an existing lock 247 genlock_lock lock; 248 lock.fd = hnd->genlockHandle; 249 if (ioctl(fd, GENLOCK_IOC_ATTACH, &lock)) { 250 ALOGE("%s: GENLOCK_IOC_ATTACH failed (err=%s)", __FUNCTION__, 251 strerror(errno)); 252 close_genlock_fd_and_handle(fd, lock.fd); 253 ret = GENLOCK_FAILURE; 254 } 255 256 // Store the relavant information in the handle 257 hnd->genlockPrivFd = fd; 258 } 259 #endif 260 return ret; 261 } 262 263 /* 264 * Lock the buffer specified by the buffer handle. The lock held by the buffer 265 * is specified by the lockType. This function will block if a write lock is 266 * requested on the buffer which has previously been locked for a read or write 267 * operation. A buffer can be locked by multiple clients for read. An optional 268 * timeout value can be specified. By default, there is no timeout. 269 * 270 * @param: handle of the buffer 271 * @param: type of lock to be acquired by the buffer. 272 * @param: timeout value in ms. GENLOCK_MAX_TIMEOUT is the maximum timeout value. 273 * @return error status. 274 */ 275 genlock_status_t genlock_lock_buffer(native_handle_t *buffer_handle, 276 genlock_lock_type_t lockType, 277 int timeout) 278 { 279 genlock_status_t ret = GENLOCK_NO_ERROR; 280 #ifdef USE_GENLOCK 281 // Translate the locktype 282 int kLockType = get_kernel_lock_type(lockType); 283 if (-1 == kLockType) { 284 ALOGE("%s: invalid lockType", __FUNCTION__); 285 return GENLOCK_FAILURE; 286 } 287 288 if (0 == timeout) { 289 ALOGW("%s: trying to lock a buffer with timeout = 0", __FUNCTION__); 290 } 291 // Call the private function to perform the lock operation specified. 292 ret = perform_lock_unlock_operation(buffer_handle, kLockType, timeout, 0); 293 #endif 294 return ret; 295 } 296 297 298 /* 299 * Unlocks a buffer that has previously been locked by the client. 300 * 301 * @param: handle of the buffer to be unlocked. 302 * @return: error status. 303 */ 304 genlock_status_t genlock_unlock_buffer(native_handle_t *buffer_handle) 305 { 306 genlock_status_t ret = GENLOCK_NO_ERROR; 307 #ifdef USE_GENLOCK 308 // Do the unlock operation by setting the unlock flag. Timeout is always 309 // 0 in this case. 310 ret = perform_lock_unlock_operation(buffer_handle, GENLOCK_UNLOCK, 0, 0); 311 #endif 312 return ret; 313 } 314 315 /* 316 * Blocks the calling process until the lock held on the handle is unlocked. 317 * 318 * @param: handle of the buffer 319 * @param: timeout value for the wait. 320 * return: error status. 321 */ 322 genlock_status_t genlock_wait(native_handle_t *buffer_handle, int timeout) { 323 #ifdef USE_GENLOCK 324 if (private_handle_t::validate(buffer_handle)) { 325 ALOGE("%s: handle is invalid", __FUNCTION__); 326 return GENLOCK_FAILURE; 327 } 328 329 private_handle_t *hnd = reinterpret_cast<private_handle_t*>(buffer_handle); 330 if ((hnd->flags & private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED) == 0) { 331 if (hnd->genlockPrivFd < 0) { 332 ALOGE("%s: the lock is invalid", __FUNCTION__); 333 return GENLOCK_FAILURE; 334 } 335 336 if (0 == timeout) 337 ALOGW("%s: timeout = 0", __FUNCTION__); 338 339 genlock_lock lock; 340 lock.fd = hnd->genlockHandle; 341 lock.timeout = timeout; 342 if (ioctl(hnd->genlockPrivFd, GENLOCK_IOC_WAIT, &lock)) { 343 ALOGE("%s: GENLOCK_IOC_WAIT failed (err=%s)", __FUNCTION__, 344 strerror(errno)); 345 return GENLOCK_FAILURE; 346 } 347 } 348 #endif 349 return GENLOCK_NO_ERROR; 350 } 351 352 /* 353 * Convert a write lock that we own to a read lock 354 * 355 * @param: handle of the buffer 356 * @param: timeout value for the wait. 357 * return: error status. 358 */ 359 genlock_status_t genlock_write_to_read(native_handle_t *buffer_handle, 360 int timeout) { 361 genlock_status_t ret = GENLOCK_NO_ERROR; 362 #ifdef USE_GENLOCK 363 if (0 == timeout) { 364 ALOGW("%s: trying to lock a buffer with timeout = 0", __FUNCTION__); 365 } 366 // Call the private function to perform the lock operation specified. 367 #ifdef GENLOCK_IOC_DREADLOCK 368 ret = perform_lock_unlock_operation(buffer_handle, GENLOCK_RDLOCK, timeout, 369 GENLOCK_WRITE_TO_READ); 370 #else 371 // depreciated 372 ret = perform_lock_unlock_operation(buffer_handle, GENLOCK_RDLOCK, 373 timeout, 0); 374 #endif 375 #endif 376 return ret; 377 } 378