1 /* lock.c -- IOCTLs for locking -*- linux-c -*-
2 * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
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:
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
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.
28 * Rickard E. (Rik) Faith <faith@valinux.com>
29 * Gareth Hughes <gareth@valinux.com>
33 /* Gamma-specific code extracted from drm_lock.h:
35 static int DRM(flush_queue
)(drm_device_t
*dev
, int context
)
37 DECLARE_WAITQUEUE(entry
, current
);
39 drm_queue_t
*q
= dev
->queuelist
[context
];
43 atomic_inc(&q
->use_count
);
44 if (atomic_read(&q
->use_count
) > 1) {
45 atomic_inc(&q
->block_write
);
46 add_wait_queue(&q
->flush_queue
, &entry
);
47 atomic_inc(&q
->block_count
);
49 current
->state
= TASK_INTERRUPTIBLE
;
50 if (!DRM_BUFCOUNT(&q
->waitlist
)) break;
52 if (signal_pending(current
)) {
53 ret
= -EINTR
; /* Can't restart */
57 atomic_dec(&q
->block_count
);
58 current
->state
= TASK_RUNNING
;
59 remove_wait_queue(&q
->flush_queue
, &entry
);
61 atomic_dec(&q
->use_count
);
63 /* NOTE: block_write is still incremented!
64 Use drm_flush_unlock_queue to decrement. */
68 static int DRM(flush_unblock_queue
)(drm_device_t
*dev
, int context
)
70 drm_queue_t
*q
= dev
->queuelist
[context
];
74 atomic_inc(&q
->use_count
);
75 if (atomic_read(&q
->use_count
) > 1) {
76 if (atomic_read(&q
->block_write
)) {
77 atomic_dec(&q
->block_write
);
78 wake_up_interruptible(&q
->write_queue
);
81 atomic_dec(&q
->use_count
);
85 int DRM(flush_block_and_flush
)(drm_device_t
*dev
, int context
,
86 drm_lock_flags_t flags
)
93 if (flags
& _DRM_LOCK_FLUSH
) {
94 ret
= DRM(flush_queue
)(dev
, DRM_KERNEL_CONTEXT
);
95 if (!ret
) ret
= DRM(flush_queue
)(dev
, context
);
97 if (flags
& _DRM_LOCK_FLUSH_ALL
) {
98 for (i
= 0; !ret
&& i
< dev
->queue_count
; i
++) {
99 ret
= DRM(flush_queue
)(dev
, i
);
105 int DRM(flush_unblock
)(drm_device_t
*dev
, int context
, drm_lock_flags_t flags
)
112 if (flags
& _DRM_LOCK_FLUSH
) {
113 ret
= DRM(flush_unblock_queue
)(dev
, DRM_KERNEL_CONTEXT
);
114 if (!ret
) ret
= DRM(flush_unblock_queue
)(dev
, context
);
116 if (flags
& _DRM_LOCK_FLUSH_ALL
) {
117 for (i
= 0; !ret
&& i
< dev
->queue_count
; i
++) {
118 ret
= DRM(flush_unblock_queue
)(dev
, i
);
125 int DRM(finish
)(struct inode
*inode
, struct file
*filp
, unsigned int cmd
,
128 drm_file_t
*priv
= filp
->private_data
;
129 drm_device_t
*dev
= priv
->dev
;
135 if (copy_from_user(&lock
, (drm_lock_t __user
*)arg
, sizeof(lock
)))
137 ret
= DRM(flush_block_and_flush
)(dev
, lock
.context
, lock
.flags
);
138 DRM(flush_unblock
)(dev
, lock
.context
, lock
.flags
);