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 #include <linux/genlock.h> 34 #include <fcntl.h> 35 #include <sys/ioctl.h> 36 37 #include "genlock.h" 38 39 #define GENLOCK_DEVICE "/dev/genlock" 40 41 namespace { 42 /* Internal function to map the userspace locks to the kernel lock types */ 43 int get_kernel_lock_type(genlock_lock_type lockType) 44 { 45 int kLockType = 0; 46 #ifdef USE_GENLOCK 47 // If the user sets both a read and write lock, higher preference is 48 // given to the write lock. 49 if (lockType & GENLOCK_WRITE_LOCK) { 50 kLockType = GENLOCK_WRLOCK; 51 } else if (lockType & GENLOCK_READ_LOCK) { 52 kLockType = GENLOCK_RDLOCK; 53 } else { 54 ALOGE("%s: invalid lockType (lockType = %d)", 55 __FUNCTION__, lockType); 56 return -1; 57 } 58 #endif 59 return kLockType; 60 } 61 62 /* Internal function to perform the actual lock/unlock operations */ 63 genlock_status_t perform_lock_unlock_operation(native_handle_t *buffer_handle, 64 int lockType, int timeout, 65 int flags) 66 { 67 #ifdef USE_GENLOCK 68 if (private_handle_t::validate(buffer_handle)) { 69 ALOGE("%s: handle is invalid", __FUNCTION__); 70 return GENLOCK_FAILURE; 71 } 72 73 private_handle_t *hnd = reinterpret_cast<private_handle_t*> 74 (buffer_handle); 75 if ((hnd->flags & private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED) == 0) { 76 if (hnd->genlockPrivFd < 0) { 77 ALOGE("%s: the lock has not been created," 78 "or has not been attached", __FUNCTION__); 79 return GENLOCK_FAILURE; 80 } 81 82 genlock_lock lock; 83 lock.op = lockType; 84 lock.flags = flags; 85 lock.timeout = timeout; 86 lock.fd = hnd->genlockHandle; 87 88 #ifdef GENLOCK_IOC_DREADLOCK 89 if (ioctl(hnd->genlockPrivFd, GENLOCK_IOC_DREADLOCK, &lock)) { 90 ALOGE("%s: GENLOCK_IOC_DREADLOCK failed (lockType0x%x," 91 "err=%s fd=%d)", __FUNCTION__, 92 lockType, strerror(errno), hnd->fd); 93 if (ETIMEDOUT == errno) 94 return GENLOCK_TIMEDOUT; 95 96 return GENLOCK_FAILURE; 97 } 98 #else 99 // depreciated 100 if (ioctl(hnd->genlockPrivFd, GENLOCK_IOC_LOCK, &lock)) { 101 ALOGE("%s: GENLOCK_IOC_LOCK failed (lockType0x%x, err=%s fd=%d)" 102 ,__FUNCTION__, lockType, strerror(errno), hnd->fd); 103 if (ETIMEDOUT == errno) 104 return GENLOCK_TIMEDOUT; 105 106 return GENLOCK_FAILURE; 107 } 108 #endif 109 } 110 #endif 111 return GENLOCK_NO_ERROR; 112 } 113 114 /* Internal function to close the fd and release the handle */ 115 void close_genlock_fd_and_handle(int& fd, int& handle) 116 { 117 if (fd >=0 ) { 118 close(fd); 119 fd = -1; 120 } 121 122 if (handle >= 0) { 123 close(handle); 124 handle = -1; 125 } 126 } 127 } 128 /* 129 * Create a genlock lock. The genlock lock file descriptor and the lock 130 * handle are stored in the buffer_handle. 131 * 132 * @param: handle of the buffer 133 * @return error status. 134 */ 135 genlock_status_t genlock_create_lock(native_handle_t *buffer_handle) 136 { 137 genlock_status_t ret = GENLOCK_NO_ERROR; 138 #ifdef USE_GENLOCK 139 if (private_handle_t::validate(buffer_handle)) { 140 ALOGE("%s: handle is invalid", __FUNCTION__); 141 return GENLOCK_FAILURE; 142 } 143 144 private_handle_t *hnd = reinterpret_cast<private_handle_t*>(buffer_handle); 145 if ((hnd->flags & private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED) == 0) { 146 // Open the genlock device 147 int fd = open(GENLOCK_DEVICE, O_RDWR); 148 if (fd < 0) { 149 ALOGE("%s: open genlock device failed (err=%s)", __FUNCTION__, 150 strerror(errno)); 151 return GENLOCK_FAILURE; 152 } 153 154 // Create a new lock 155 genlock_lock lock; 156 if (ioctl(fd, GENLOCK_IOC_NEW, NULL)) { 157 ALOGE("%s: GENLOCK_IOC_NEW failed (error=%s)", __FUNCTION__, 158 strerror(errno)); 159 close_genlock_fd_and_handle(fd, lock.fd); 160 ret = GENLOCK_FAILURE; 161 } 162 163 // Export the lock for other processes to be able to use it. 164 if (GENLOCK_FAILURE != ret) { 165 if (ioctl(fd, GENLOCK_IOC_EXPORT, &lock)) { 166 ALOGE("%s: GENLOCK_IOC_EXPORT failed (error=%s)", __FUNCTION__, 167 strerror(errno)); 168 close_genlock_fd_and_handle(fd, lock.fd); 169 ret = GENLOCK_FAILURE; 170 } 171 } 172 173 // Store the lock params in the handle. 174 hnd->genlockPrivFd = fd; 175 hnd->genlockHandle = lock.fd; 176 } else { 177 hnd->genlockHandle = 0; 178 } 179 #endif 180 return ret; 181 } 182 183 184 /* 185 * Release a genlock lock associated with the handle. 186 * 187 * @param: handle of the buffer 188 * @return error status. 189 */ 190 genlock_status_t genlock_release_lock(native_handle_t *buffer_handle) 191 { 192 genlock_status_t ret = GENLOCK_NO_ERROR; 193 #ifdef USE_GENLOCK 194 if (private_handle_t::validate(buffer_handle)) { 195 ALOGE("%s: handle is invalid", __FUNCTION__); 196 return GENLOCK_FAILURE; 197 } 198 199 private_handle_t *hnd = reinterpret_cast<private_handle_t*>(buffer_handle); 200 if ((hnd->flags & private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED) == 0) { 201 if (hnd->genlockPrivFd < 0) { 202 ALOGE("%s: the lock is invalid", __FUNCTION__); 203 return GENLOCK_FAILURE; 204 } 205 206 // Close the fd and reset the parameters. 207 close_genlock_fd_and_handle(hnd->genlockPrivFd, hnd->genlockHandle); 208 } 209 #endif 210 return ret; 211 } 212 213 214 /* 215 * Attach a lock to the buffer handle passed via an IPC. 216 * 217 * @param: handle of the buffer 218 * @return error status. 219 */ 220 genlock_status_t genlock_attach_lock(native_handle_t *buffer_handle) 221 { 222 genlock_status_t ret = GENLOCK_NO_ERROR; 223 #ifdef USE_GENLOCK 224 if (private_handle_t::validate(buffer_handle)) { 225 ALOGE("%s: handle is invalid", __FUNCTION__); 226 return GENLOCK_FAILURE; 227 } 228 229 private_handle_t *hnd = reinterpret_cast<private_handle_t*>(buffer_handle); 230 if ((hnd->flags & private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED) == 0) { 231 // Open the genlock device 232 int fd = open(GENLOCK_DEVICE, O_RDWR); 233 if (fd < 0) { 234 ALOGE("%s: open genlock device failed (err=%s)", __FUNCTION__, 235 strerror(errno)); 236 return GENLOCK_FAILURE; 237 } 238 239 // Attach the local handle to an existing lock 240 genlock_lock lock; 241 lock.fd = hnd->genlockHandle; 242 if (ioctl(fd, GENLOCK_IOC_ATTACH, &lock)) { 243 ALOGE("%s: GENLOCK_IOC_ATTACH failed (err=%s)", __FUNCTION__, 244 strerror(errno)); 245 close_genlock_fd_and_handle(fd, lock.fd); 246 ret = GENLOCK_FAILURE; 247 } 248 249 // Store the relavant information in the handle 250 hnd->genlockPrivFd = fd; 251 } 252 #endif 253 return ret; 254 } 255 256 /* 257 * Lock the buffer specified by the buffer handle. The lock held by the buffer 258 * is specified by the lockType. This function will block if a write lock is 259 * requested on the buffer which has previously been locked for a read or write 260 * operation. A buffer can be locked by multiple clients for read. An optional 261 * timeout value can be specified. By default, there is no timeout. 262 * 263 * @param: handle of the buffer 264 * @param: type of lock to be acquired by the buffer. 265 * @param: timeout value in ms. GENLOCK_MAX_TIMEOUT is the maximum timeout value. 266 * @return error status. 267 */ 268 genlock_status_t genlock_lock_buffer(native_handle_t *buffer_handle, 269 genlock_lock_type_t lockType, 270 int timeout) 271 { 272 genlock_status_t ret = GENLOCK_NO_ERROR; 273 #ifdef USE_GENLOCK 274 // Translate the locktype 275 int kLockType = get_kernel_lock_type(lockType); 276 if (-1 == kLockType) { 277 ALOGE("%s: invalid lockType", __FUNCTION__); 278 return GENLOCK_FAILURE; 279 } 280 281 if (0 == timeout) { 282 ALOGW("%s: trying to lock a buffer with timeout = 0", __FUNCTION__); 283 } 284 // Call the private function to perform the lock operation specified. 285 ret = perform_lock_unlock_operation(buffer_handle, kLockType, timeout, 0); 286 #endif 287 return ret; 288 } 289 290 291 /* 292 * Unlocks a buffer that has previously been locked by the client. 293 * 294 * @param: handle of the buffer to be unlocked. 295 * @return: error status. 296 */ 297 genlock_status_t genlock_unlock_buffer(native_handle_t *buffer_handle) 298 { 299 genlock_status_t ret = GENLOCK_NO_ERROR; 300 #ifdef USE_GENLOCK 301 // Do the unlock operation by setting the unlock flag. Timeout is always 302 // 0 in this case. 303 ret = perform_lock_unlock_operation(buffer_handle, GENLOCK_UNLOCK, 0, 0); 304 #endif 305 return ret; 306 } 307 308 /* 309 * Blocks the calling process until the lock held on the handle is unlocked. 310 * 311 * @param: handle of the buffer 312 * @param: timeout value for the wait. 313 * return: error status. 314 */ 315 genlock_status_t genlock_wait(native_handle_t *buffer_handle, int timeout) { 316 #ifdef USE_GENLOCK 317 if (private_handle_t::validate(buffer_handle)) { 318 ALOGE("%s: handle is invalid", __FUNCTION__); 319 return GENLOCK_FAILURE; 320 } 321 322 private_handle_t *hnd = reinterpret_cast<private_handle_t*>(buffer_handle); 323 if ((hnd->flags & private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED) == 0) { 324 if (hnd->genlockPrivFd < 0) { 325 ALOGE("%s: the lock is invalid", __FUNCTION__); 326 return GENLOCK_FAILURE; 327 } 328 329 if (0 == timeout) 330 ALOGW("%s: timeout = 0", __FUNCTION__); 331 332 genlock_lock lock; 333 lock.fd = hnd->genlockHandle; 334 lock.timeout = timeout; 335 if (ioctl(hnd->genlockPrivFd, GENLOCK_IOC_WAIT, &lock)) { 336 ALOGE("%s: GENLOCK_IOC_WAIT failed (err=%s)", __FUNCTION__, 337 strerror(errno)); 338 return GENLOCK_FAILURE; 339 } 340 } 341 #endif 342 return GENLOCK_NO_ERROR; 343 } 344 345 /* 346 * Convert a write lock that we own to a read lock 347 * 348 * @param: handle of the buffer 349 * @param: timeout value for the wait. 350 * return: error status. 351 */ 352 genlock_status_t genlock_write_to_read(native_handle_t *buffer_handle, 353 int timeout) { 354 genlock_status_t ret = GENLOCK_NO_ERROR; 355 #ifdef USE_GENLOCK 356 if (0 == timeout) { 357 ALOGW("%s: trying to lock a buffer with timeout = 0", __FUNCTION__); 358 } 359 // Call the private function to perform the lock operation specified. 360 #ifdef GENLOCK_IOC_DREADLOCK 361 ret = perform_lock_unlock_operation(buffer_handle, GENLOCK_RDLOCK, timeout, 362 GENLOCK_WRITE_TO_READ); 363 #else 364 // depreciated 365 ret = perform_lock_unlock_operation(buffer_handle, GENLOCK_RDLOCK, 366 timeout, 0); 367 #endif 368 #endif 369 return ret; 370 } 371