gamma_lock.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /* lock.c -- IOCTLs for locking -*- linux-c -*-
  2. * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
  3. *
  4. * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  5. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  6. * All Rights Reserved.
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a
  9. * copy of this software and associated documentation files (the "Software"),
  10. * to deal in the Software without restriction, including without limitation
  11. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  12. * and/or sell copies of the Software, and to permit persons to whom the
  13. * Software is furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice (including the next
  16. * paragraph) shall be included in all copies or substantial portions of the
  17. * Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  22. * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  23. * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  24. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  25. * OTHER DEALINGS IN THE SOFTWARE.
  26. *
  27. * Authors:
  28. * Rickard E. (Rik) Faith <faith@valinux.com>
  29. * Gareth Hughes <gareth@valinux.com>
  30. */
  31. /* Gamma-specific code extracted from drm_lock.h:
  32. */
  33. static int DRM(flush_queue)(drm_device_t *dev, int context)
  34. {
  35. DECLARE_WAITQUEUE(entry, current);
  36. int ret = 0;
  37. drm_queue_t *q = dev->queuelist[context];
  38. DRM_DEBUG("\n");
  39. atomic_inc(&q->use_count);
  40. if (atomic_read(&q->use_count) > 1) {
  41. atomic_inc(&q->block_write);
  42. add_wait_queue(&q->flush_queue, &entry);
  43. atomic_inc(&q->block_count);
  44. for (;;) {
  45. current->state = TASK_INTERRUPTIBLE;
  46. if (!DRM_BUFCOUNT(&q->waitlist)) break;
  47. schedule();
  48. if (signal_pending(current)) {
  49. ret = -EINTR; /* Can't restart */
  50. break;
  51. }
  52. }
  53. atomic_dec(&q->block_count);
  54. current->state = TASK_RUNNING;
  55. remove_wait_queue(&q->flush_queue, &entry);
  56. }
  57. atomic_dec(&q->use_count);
  58. /* NOTE: block_write is still incremented!
  59. Use drm_flush_unlock_queue to decrement. */
  60. return ret;
  61. }
  62. static int DRM(flush_unblock_queue)(drm_device_t *dev, int context)
  63. {
  64. drm_queue_t *q = dev->queuelist[context];
  65. DRM_DEBUG("\n");
  66. atomic_inc(&q->use_count);
  67. if (atomic_read(&q->use_count) > 1) {
  68. if (atomic_read(&q->block_write)) {
  69. atomic_dec(&q->block_write);
  70. wake_up_interruptible(&q->write_queue);
  71. }
  72. }
  73. atomic_dec(&q->use_count);
  74. return 0;
  75. }
  76. int DRM(flush_block_and_flush)(drm_device_t *dev, int context,
  77. drm_lock_flags_t flags)
  78. {
  79. int ret = 0;
  80. int i;
  81. DRM_DEBUG("\n");
  82. if (flags & _DRM_LOCK_FLUSH) {
  83. ret = DRM(flush_queue)(dev, DRM_KERNEL_CONTEXT);
  84. if (!ret) ret = DRM(flush_queue)(dev, context);
  85. }
  86. if (flags & _DRM_LOCK_FLUSH_ALL) {
  87. for (i = 0; !ret && i < dev->queue_count; i++) {
  88. ret = DRM(flush_queue)(dev, i);
  89. }
  90. }
  91. return ret;
  92. }
  93. int DRM(flush_unblock)(drm_device_t *dev, int context, drm_lock_flags_t flags)
  94. {
  95. int ret = 0;
  96. int i;
  97. DRM_DEBUG("\n");
  98. if (flags & _DRM_LOCK_FLUSH) {
  99. ret = DRM(flush_unblock_queue)(dev, DRM_KERNEL_CONTEXT);
  100. if (!ret) ret = DRM(flush_unblock_queue)(dev, context);
  101. }
  102. if (flags & _DRM_LOCK_FLUSH_ALL) {
  103. for (i = 0; !ret && i < dev->queue_count; i++) {
  104. ret = DRM(flush_unblock_queue)(dev, i);
  105. }
  106. }
  107. return ret;
  108. }
  109. int DRM(finish)(struct inode *inode, struct file *filp, unsigned int cmd,
  110. unsigned long arg)
  111. {
  112. drm_file_t *priv = filp->private_data;
  113. drm_device_t *dev = priv->dev;
  114. int ret = 0;
  115. drm_lock_t lock;
  116. DRM_DEBUG("\n");
  117. if (copy_from_user(&lock, (drm_lock_t __user *)arg, sizeof(lock)))
  118. return -EFAULT;
  119. ret = DRM(flush_block_and_flush)(dev, lock.context, lock.flags);
  120. DRM(flush_unblock)(dev, lock.context, lock.flags);
  121. return ret;
  122. }