Advertisement
superr

genlock.cpp

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