OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [drm/] [drm_lock.h] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* 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
 
32
#include "drmP.h"
33
 
34
int DRM(block)(struct inode *inode, struct file *filp, unsigned int cmd,
35
               unsigned long arg)
36
{
37
        DRM_DEBUG("\n");
38
        return 0;
39
}
40
 
41
int DRM(unblock)(struct inode *inode, struct file *filp, unsigned int cmd,
42
                 unsigned long arg)
43
{
44
        DRM_DEBUG("\n");
45
        return 0;
46
}
47
 
48
int DRM(lock_take)(__volatile__ unsigned int *lock, unsigned int context)
49
{
50
        unsigned int old, new, prev;
51
 
52
        do {
53
                old = *lock;
54
                if (old & _DRM_LOCK_HELD) new = old | _DRM_LOCK_CONT;
55
                else                      new = context | _DRM_LOCK_HELD;
56
                prev = cmpxchg(lock, old, new);
57
        } while (prev != old);
58
        if (_DRM_LOCKING_CONTEXT(old) == context) {
59
                if (old & _DRM_LOCK_HELD) {
60
                        if (context != DRM_KERNEL_CONTEXT) {
61
                                DRM_ERROR("%d holds heavyweight lock\n",
62
                                          context);
63
                        }
64
                        return 0;
65
                }
66
        }
67
        if (new == (context | _DRM_LOCK_HELD)) {
68
                                /* Have lock */
69
                return 1;
70
        }
71
        return 0;
72
}
73
 
74
/* This takes a lock forcibly and hands it to context.  Should ONLY be used
75
   inside *_unlock to give lock to kernel before calling *_dma_schedule. */
76
int DRM(lock_transfer)(drm_device_t *dev,
77
                       __volatile__ unsigned int *lock, unsigned int context)
78
{
79
        unsigned int old, new, prev;
80
 
81
        dev->lock.pid = 0;
82
        do {
83
                old  = *lock;
84
                new  = context | _DRM_LOCK_HELD;
85
                prev = cmpxchg(lock, old, new);
86
        } while (prev != old);
87
        return 1;
88
}
89
 
90
int DRM(lock_free)(drm_device_t *dev,
91
                   __volatile__ unsigned int *lock, unsigned int context)
92
{
93
        unsigned int old, new, prev;
94
        pid_t        pid = dev->lock.pid;
95
 
96
        dev->lock.pid = 0;
97
        do {
98
                old  = *lock;
99
                new  = 0;
100
                prev = cmpxchg(lock, old, new);
101
        } while (prev != old);
102
        if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) {
103
                DRM_ERROR("%d freed heavyweight lock held by %d (pid %d)\n",
104
                          context,
105
                          _DRM_LOCKING_CONTEXT(old),
106
                          pid);
107
                return 1;
108
        }
109
        wake_up_interruptible(&dev->lock.lock_queue);
110
        return 0;
111
}
112
 
113
static int DRM(flush_queue)(drm_device_t *dev, int context)
114
{
115
        DECLARE_WAITQUEUE(entry, current);
116
        int               ret   = 0;
117
        drm_queue_t       *q    = dev->queuelist[context];
118
 
119
        DRM_DEBUG("\n");
120
 
121
        atomic_inc(&q->use_count);
122
        if (atomic_read(&q->use_count) > 1) {
123
                atomic_inc(&q->block_write);
124
                add_wait_queue(&q->flush_queue, &entry);
125
                atomic_inc(&q->block_count);
126
                for (;;) {
127
                        current->state = TASK_INTERRUPTIBLE;
128
                        if (!DRM_BUFCOUNT(&q->waitlist)) break;
129
                        schedule();
130
                        if (signal_pending(current)) {
131
                                ret = -EINTR; /* Can't restart */
132
                                break;
133
                        }
134
                }
135
                atomic_dec(&q->block_count);
136
                current->state = TASK_RUNNING;
137
                remove_wait_queue(&q->flush_queue, &entry);
138
        }
139
        atomic_dec(&q->use_count);
140
 
141
                                /* NOTE: block_write is still incremented!
142
                                   Use drm_flush_unlock_queue to decrement. */
143
        return ret;
144
}
145
 
146
static int DRM(flush_unblock_queue)(drm_device_t *dev, int context)
147
{
148
        drm_queue_t       *q    = dev->queuelist[context];
149
 
150
        DRM_DEBUG("\n");
151
 
152
        atomic_inc(&q->use_count);
153
        if (atomic_read(&q->use_count) > 1) {
154
                if (atomic_read(&q->block_write)) {
155
                        atomic_dec(&q->block_write);
156
                        wake_up_interruptible(&q->write_queue);
157
                }
158
        }
159
        atomic_dec(&q->use_count);
160
        return 0;
161
}
162
 
163
int DRM(flush_block_and_flush)(drm_device_t *dev, int context,
164
                               drm_lock_flags_t flags)
165
{
166
        int ret = 0;
167
        int i;
168
 
169
        DRM_DEBUG("\n");
170
 
171
        if (flags & _DRM_LOCK_FLUSH) {
172
                ret = DRM(flush_queue)(dev, DRM_KERNEL_CONTEXT);
173
                if (!ret) ret = DRM(flush_queue)(dev, context);
174
        }
175
        if (flags & _DRM_LOCK_FLUSH_ALL) {
176
                for (i = 0; !ret && i < dev->queue_count; i++) {
177
                        ret = DRM(flush_queue)(dev, i);
178
                }
179
        }
180
        return ret;
181
}
182
 
183
int DRM(flush_unblock)(drm_device_t *dev, int context, drm_lock_flags_t flags)
184
{
185
        int ret = 0;
186
        int i;
187
 
188
        DRM_DEBUG("\n");
189
 
190
        if (flags & _DRM_LOCK_FLUSH) {
191
                ret = DRM(flush_unblock_queue)(dev, DRM_KERNEL_CONTEXT);
192
                if (!ret) ret = DRM(flush_unblock_queue)(dev, context);
193
        }
194
        if (flags & _DRM_LOCK_FLUSH_ALL) {
195
                for (i = 0; !ret && i < dev->queue_count; i++) {
196
                        ret = DRM(flush_unblock_queue)(dev, i);
197
                }
198
        }
199
 
200
        return ret;
201
}
202
 
203
int DRM(finish)(struct inode *inode, struct file *filp, unsigned int cmd,
204
                unsigned long arg)
205
{
206
        drm_file_t        *priv   = filp->private_data;
207
        drm_device_t      *dev    = priv->dev;
208
        int               ret     = 0;
209
        drm_lock_t        lock;
210
 
211
        DRM_DEBUG("\n");
212
 
213
        if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
214
                return -EFAULT;
215
        ret = DRM(flush_block_and_flush)(dev, lock.context, lock.flags);
216
        DRM(flush_unblock)(dev, lock.context, lock.flags);
217
        return ret;
218
}
219
 
220
/* If we get here, it means that the process has called DRM_IOCTL_LOCK
221
   without calling DRM_IOCTL_UNLOCK.
222
 
223
   If the lock is not held, then let the signal proceed as usual.
224
 
225
   If the lock is held, then set the contended flag and keep the signal
226
   blocked.
227
 
228
 
229
   Return 1 if the signal should be delivered normally.
230
   Return 0 if the signal should be blocked.  */
231
 
232
int DRM(notifier)(void *priv)
233
{
234
        drm_sigdata_t *s = (drm_sigdata_t *)priv;
235
        unsigned int  old, new, prev;
236
 
237
 
238
                                /* Allow signal delivery if lock isn't held */
239
        if (!s->lock || !_DRM_LOCK_IS_HELD(s->lock->lock)
240
            || _DRM_LOCKING_CONTEXT(s->lock->lock) != s->context) return 1;
241
 
242
                                /* Otherwise, set flag to force call to
243
                                   drmUnlock */
244
        do {
245
                old  = s->lock->lock;
246
                new  = old | _DRM_LOCK_CONT;
247
                prev = cmpxchg(&s->lock->lock, old, new);
248
        } while (prev != old);
249
        return 0;
250
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.