Woops, missed the updated patch description.. Op 15-01-13 13:33, Maarten Lankhorst schreef: > makes it easier to port ttm over.. > > Signed-off-by: Maarten Lankhorst <maarten.lankhorst@xxxxxxxxxxxxx> mutex_reserve_lock, and mutex_reserve_lock_interruptible: Lock a buffer with a reservation_id set. reservation_id must not be set to 0, since this is a special value that means no reservation_id. Normally if reservation_id is not set, or is older than the reservation_id that's currently set on the mutex, the behavior will be to wait normally. However, if the reservation_id is newer than the current reservation_id, -EAGAIN will be returned, and this function must unreserve all other mutexes and then redo a blocking lock with normal mutex calls to prevent a deadlock, then call mutex_locked_set_reservation on successful locking to set the reservation_id inside the lock. These functions will return -EDEADLK instead of -EAGAIN if reservation_id is the same as the reservation_id that's attempted to lock the mutex with, since in that case you presumably attempted to lock the same lock twice. mutex_reserve_lock_slow and mutex_reserve_lock_intr_slow: Similar to mutex_reserve_lock, except it won't backoff with -EAGAIN. This is useful after mutex_reserve_lock failed with -EAGAIN, and you unreserved all buffers so no deadlock can occur. mutex_unreserve_unlock: Unlock a buffer reserved with the previous calls. Missing at the moment, maybe TODO? * lockdep warnings when wrongly calling mutex_unreserve_unlock or mutex_unlock, depending on whether reservation_id was set previously or not. - Does lockdep have something for this or do I need to extend struct mutex? * Check if lockdep warns if you unlock a lock that other locks were nested to. - spin_lock(m); spin_lock_nest_lock(a, m); spin_unlock(m); spin_unlock(a); would be nice if it gave a splat. Have to recheck if it does, though.. Design: I chose for ticket_mutex to encapsulate struct mutex, so the extra memory usage and atomic set on init will only happen when you deliberately create a ticket lock. Since the mutexes are mostly meant to protect buffer object serialization in ttm, not much contention is expected. I could be slightly smarter with wakeups, but this would be at the expense at adding a field to struct mutex_waiter. Because this would add overhead to all cases where ticket_mutexes are not used, and ticket_mutexes are less performance sensitive anyway since they only protect buffer objects, I didn't want to do this. It's still better than ttm always calling wake_up_all, which does a unconditional spin_lock_irqsave/irqrestore. I needed this in kernel/mutex.c because of the extensions to __lock_common, which are hopefully optimized away for all normal paths. Changes since RFC patch v1: - Updated to use atomic_long instead of atomic, since the reservation_id was a long. - added mutex_reserve_lock_slow and mutex_reserve_lock_intr_slow - removed mutex_locked_set_reservation_id (or w/e it was called) Signed-off-by: Maarten Lankhorst <maarten.lankhorst@xxxxxxxxxxxxx> > --- > include/linux/mutex.h | 86 +++++++++++++- > kernel/mutex.c | 317 +++++++++++++++++++++++++++++++++++++++++++++++--- > 2 files changed, 387 insertions(+), 16 deletions(-) > > diff --git a/include/linux/mutex.h b/include/linux/mutex.h > index 9121595..602c247 100644 > --- a/include/linux/mutex.h > +++ b/include/linux/mutex.h > @@ -62,6 +62,11 @@ struct mutex { > #endif > }; > > +struct ticket_mutex { > + struct mutex base; > + atomic_long_t reservation_id; > +}; > + > /* > * This is the control structure for tasks blocked on mutex, > * which resides on the blocked task's kernel stack: > @@ -109,12 +114,24 @@ static inline void mutex_destroy(struct mutex *lock) {} > __DEBUG_MUTEX_INITIALIZER(lockname) \ > __DEP_MAP_MUTEX_INITIALIZER(lockname) } > > +#define __TICKET_MUTEX_INITIALIZER(lockname) \ > + { .base = __MUTEX_INITIALIZER(lockname) \ > + , .reservation_id = ATOMIC_LONG_INIT(0) } > + > #define DEFINE_MUTEX(mutexname) \ > struct mutex mutexname = __MUTEX_INITIALIZER(mutexname) > > extern void __mutex_init(struct mutex *lock, const char *name, > struct lock_class_key *key); > > +static inline void __ticket_mutex_init(struct ticket_mutex *lock, > + const char *name, > + struct lock_class_key *key) > +{ > + __mutex_init(&lock->base, name, key); > + atomic_long_set(&lock->reservation_id, 0); > +} > + > /** > * mutex_is_locked - is the mutex locked > * @lock: the mutex to be queried > @@ -133,26 +150,91 @@ static inline int mutex_is_locked(struct mutex *lock) > #ifdef CONFIG_DEBUG_LOCK_ALLOC > extern void mutex_lock_nested(struct mutex *lock, unsigned int subclass); > extern void _mutex_lock_nest_lock(struct mutex *lock, struct lockdep_map *nest_lock); > + > extern int __must_check mutex_lock_interruptible_nested(struct mutex *lock, > unsigned int subclass); > extern int __must_check mutex_lock_killable_nested(struct mutex *lock, > unsigned int subclass); > > +extern int __must_check _mutex_reserve_lock(struct ticket_mutex *lock, > + struct lockdep_map *nest_lock, > + unsigned long reservation_id); > + > +extern int __must_check _mutex_reserve_lock_interruptible(struct ticket_mutex *, > + struct lockdep_map *nest_lock, > + unsigned long reservation_id); > + > +extern void _mutex_reserve_lock_slow(struct ticket_mutex *lock, > + struct lockdep_map *nest_lock, > + unsigned long reservation_id); > + > +extern int __must_check _mutex_reserve_lock_intr_slow(struct ticket_mutex *, > + struct lockdep_map *nest_lock, > + unsigned long reservation_id); > + > #define mutex_lock(lock) mutex_lock_nested(lock, 0) > #define mutex_lock_interruptible(lock) mutex_lock_interruptible_nested(lock, 0) > #define mutex_lock_killable(lock) mutex_lock_killable_nested(lock, 0) > > #define mutex_lock_nest_lock(lock, nest_lock) \ > do { \ > - typecheck(struct lockdep_map *, &(nest_lock)->dep_map); \ > + typecheck(struct lockdep_map *, &(nest_lock)->dep_map); \ > _mutex_lock_nest_lock(lock, &(nest_lock)->dep_map); \ > } while (0) > > +#define mutex_reserve_lock(lock, nest_lock, reservation_id) \ > +({ \ > + typecheck(struct lockdep_map *, &(nest_lock)->dep_map); \ > + _mutex_reserve_lock(lock, &(nest_lock)->dep_map, reservation_id); \ > +}) > + > +#define mutex_reserve_lock_interruptible(lock, nest_lock, reservation_id) \ > +({ \ > + typecheck(struct lockdep_map *, &(nest_lock)->dep_map); \ > + _mutex_reserve_lock_interruptible(lock, &(nest_lock)->dep_map, \ > + reservation_id); \ > +}) > + > +#define mutex_reserve_lock_slow(lock, nest_lock, reservation_id) \ > +do { \ > + typecheck(struct lockdep_map *, &(nest_lock)->dep_map); \ > + _mutex_reserve_lock_slow(lock, &(nest_lock)->dep_map, reservation_id); \ > +} while (0) > + > +#define mutex_reserve_lock_intr_slow(lock, nest_lock, reservation_id) \ > +({ \ > + typecheck(struct lockdep_map *, &(nest_lock)->dep_map); \ > + _mutex_reserve_lock_intr_slow(lock, &(nest_lock)->dep_map, \ > + reservation_id); \ > +}) > + > #else > extern void mutex_lock(struct mutex *lock); > extern int __must_check mutex_lock_interruptible(struct mutex *lock); > extern int __must_check mutex_lock_killable(struct mutex *lock); > > +extern int __must_check _mutex_reserve_lock(struct ticket_mutex *lock, > + unsigned long reservation_id); > +extern int __must_check _mutex_reserve_lock_interruptible(struct ticket_mutex *, > + unsigned long reservation_id); > + > +extern void _mutex_reserve_lock_slow(struct ticket_mutex *lock, > + unsigned long reservation_id); > +extern int __must_check _mutex_reserve_lock_intr_slow(struct ticket_mutex *, > + unsigned long reservation_id); > + > +#define mutex_reserve_lock(lock, nest_lock, reservation_id) \ > + _mutex_reserve_lock(lock, reservation_id) > + > +#define mutex_reserve_lock_interruptible(lock, nest_lock, reservation_id) \ > + _mutex_reserve_lock_interruptible(lock, reservation_id) > + > +#define mutex_reserve_lock_slow(lock, nest_lock, reservation_id) \ > + _mutex_reserve_lock_slow(lock, reservation_id) > + > +#define mutex_reserve_lock_intr_slow(lock, nest_lock, reservation_id) \ > + _mutex_reserve_lock_intr_slow(lock, reservation_id) > + > # define mutex_lock_nested(lock, subclass) mutex_lock(lock) > # define mutex_lock_interruptible_nested(lock, subclass) mutex_lock_interruptible(lock) > # define mutex_lock_killable_nested(lock, subclass) mutex_lock_killable(lock) > @@ -167,6 +249,8 @@ extern int __must_check mutex_lock_killable(struct mutex *lock); > */ > extern int mutex_trylock(struct mutex *lock); > extern void mutex_unlock(struct mutex *lock); > +extern void mutex_unreserve_unlock(struct ticket_mutex *lock); > + > extern int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock); > > #ifndef CONFIG_HAVE_ARCH_MUTEX_CPU_RELAX > diff --git a/kernel/mutex.c b/kernel/mutex.c > index a307cc9..8282729 100644 > --- a/kernel/mutex.c > +++ b/kernel/mutex.c > @@ -126,16 +126,119 @@ void __sched mutex_unlock(struct mutex *lock) > > EXPORT_SYMBOL(mutex_unlock); > > +/** > + * mutex_unreserve_unlock - release the mutex > + * @lock: the mutex to be released > + * > + * Unlock a mutex that has been locked by this task previously > + * with _mutex_reserve_lock*. > + * > + * This function must not be used in interrupt context. Unlocking > + * of a not locked mutex is not allowed. > + */ > +void __sched mutex_unreserve_unlock(struct ticket_mutex *lock) > +{ > + /* > + * mark mutex as no longer part of a reservation, next > + * locker can set this again > + */ > + atomic_long_set(&lock->reservation_id, 0); > + > + /* > + * The unlocking fastpath is the 0->1 transition from 'locked' > + * into 'unlocked' state: > + */ > +#ifndef CONFIG_DEBUG_MUTEXES > + /* > + * When debugging is enabled we must not clear the owner before time, > + * the slow path will always be taken, and that clears the owner field > + * after verifying that it was indeed current. > + */ > + mutex_clear_owner(&lock->base); > +#endif > + __mutex_fastpath_unlock(&lock->base.count, __mutex_unlock_slowpath); > +} > +EXPORT_SYMBOL(mutex_unreserve_unlock); > + > +static inline int __sched > +__mutex_lock_check_reserve(struct mutex *lock, unsigned long reservation_id) > +{ > + struct ticket_mutex *m = container_of(lock, struct ticket_mutex, base); > + unsigned long cur_id; > + > + cur_id = atomic_long_read(&m->reservation_id); > + if (!cur_id) > + return 0; > + > + if (unlikely(reservation_id == cur_id)) > + return -EDEADLK; > + > + if (unlikely(reservation_id - cur_id <= LONG_MAX)) > + return -EAGAIN; > + > + return 0; > +} > + > +/* > + * after acquiring lock with fastpath or when we lost out in contested > + * slowpath, set reservation_id and wake up any waiters so they can recheck. > + */ > +static __always_inline void > +mutex_set_reservation_fastpath(struct ticket_mutex *lock, > + unsigned long reservation_id, bool check_res) > +{ > + unsigned long flags; > + struct mutex_waiter *cur; > + > + if (check_res || config_enabled(CONFIG_DEBUG_LOCK_ALLOC)) { > + unsigned long cur_id; > + > + cur_id = atomic_long_xchg(&lock->reservation_id, > + reservation_id); > +#ifdef CONFIG_DEBUG_LOCK_ALLOC > + if (check_res) > + DEBUG_LOCKS_WARN_ON(cur_id && > + cur_id != reservation_id); > + else > + DEBUG_LOCKS_WARN_ON(cur_id); > + lockdep_assert_held(&lock->base); > +#endif > + > + if (unlikely(cur_id == reservation_id)) > + return; > + } else > + atomic_long_set(&lock->reservation_id, reservation_id); > + > + /* > + * Check if lock is contended, if not there is nobody to wake up > + */ > + if (likely(atomic_read(&lock->base.count) == 0)) > + return; > + > + /* > + * Uh oh, we raced in fastpath, wake up everyone in this case, > + * so they can see the new reservation_id > + */ > + spin_lock_mutex(&lock->base.wait_lock, flags); > + list_for_each_entry(cur, &lock->base.wait_list, list) { > + debug_mutex_wake_waiter(&lock->base, cur); > + wake_up_process(cur->task); > + } > + spin_unlock_mutex(&lock->base.wait_lock, flags); > +} > + > /* > * Lock a mutex (possibly interruptible), slowpath: > */ > static inline int __sched > __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, > - struct lockdep_map *nest_lock, unsigned long ip) > + struct lockdep_map *nest_lock, unsigned long ip, > + unsigned long reservation_id, bool res_slow) > { > struct task_struct *task = current; > struct mutex_waiter waiter; > unsigned long flags; > + int ret; > > preempt_disable(); > mutex_acquire_nest(&lock->dep_map, subclass, 0, nest_lock, ip); > @@ -162,6 +265,12 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, > for (;;) { > struct task_struct *owner; > > + if (!__builtin_constant_p(reservation_id) && !res_slow) { > + ret = __mutex_lock_check_reserve(lock, reservation_id); > + if (ret) > + goto err_nowait; > + } > + > /* > * If there's an owner, wait for it to either > * release the lock or go to sleep. > @@ -172,6 +281,13 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, > > if (atomic_cmpxchg(&lock->count, 1, 0) == 1) { > lock_acquired(&lock->dep_map, ip); > + if (res_slow) { > + struct ticket_mutex *m; > + m = container_of(lock, struct ticket_mutex, base); > + > + mutex_set_reservation_fastpath(m, reservation_id, false); > + } > + > mutex_set_owner(lock); > preempt_enable(); > return 0; > @@ -227,15 +343,16 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, > * TASK_UNINTERRUPTIBLE case.) > */ > if (unlikely(signal_pending_state(state, task))) { > - mutex_remove_waiter(lock, &waiter, > - task_thread_info(task)); > - mutex_release(&lock->dep_map, 1, ip); > - spin_unlock_mutex(&lock->wait_lock, flags); > + ret = -EINTR; > + goto err; > + } > > - debug_mutex_free_waiter(&waiter); > - preempt_enable(); > - return -EINTR; > + if (!__builtin_constant_p(reservation_id) && !res_slow) { > + ret = __mutex_lock_check_reserve(lock, reservation_id); > + if (ret) > + goto err; > } > + > __set_task_state(task, state); > > /* didn't get the lock, go to sleep: */ > @@ -250,6 +367,28 @@ done: > mutex_remove_waiter(lock, &waiter, current_thread_info()); > mutex_set_owner(lock); > > + if (!__builtin_constant_p(reservation_id)) { > + struct ticket_mutex *m; > + struct mutex_waiter *cur; > + /* > + * this should get optimized out for the common case, > + * and is only important for _mutex_reserve_lock > + */ > + > + m = container_of(lock, struct ticket_mutex, base); > + atomic_long_set(&m->reservation_id, reservation_id); > + > + /* > + * give any possible sleeping processes the chance to wake up, > + * so they can recheck if they have to back off from > + * reservations > + */ > + list_for_each_entry(cur, &lock->wait_list, list) { > + debug_mutex_wake_waiter(lock, cur); > + wake_up_process(cur->task); > + } > + } > + > /* set it to 0 if there are no waiters left: */ > if (likely(list_empty(&lock->wait_list))) > atomic_set(&lock->count, 0); > @@ -260,6 +399,19 @@ done: > preempt_enable(); > > return 0; > + > +err: > + mutex_remove_waiter(lock, &waiter, task_thread_info(task)); > + spin_unlock_mutex(&lock->wait_lock, flags); > + debug_mutex_free_waiter(&waiter); > + > +#ifdef CONFIG_MUTEX_SPIN_ON_OWNER > +err_nowait: > +#endif > + mutex_release(&lock->dep_map, 1, ip); > + > + preempt_enable(); > + return ret; > } > > #ifdef CONFIG_DEBUG_LOCK_ALLOC > @@ -267,7 +419,8 @@ void __sched > mutex_lock_nested(struct mutex *lock, unsigned int subclass) > { > might_sleep(); > - __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, subclass, NULL, _RET_IP_); > + __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, > + subclass, NULL, _RET_IP_, 0, 0); > } > > EXPORT_SYMBOL_GPL(mutex_lock_nested); > @@ -276,7 +429,8 @@ void __sched > _mutex_lock_nest_lock(struct mutex *lock, struct lockdep_map *nest) > { > might_sleep(); > - __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, 0, nest, _RET_IP_); > + __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, > + 0, nest, _RET_IP_, 0, 0); > } > > EXPORT_SYMBOL_GPL(_mutex_lock_nest_lock); > @@ -285,7 +439,8 @@ int __sched > mutex_lock_killable_nested(struct mutex *lock, unsigned int subclass) > { > might_sleep(); > - return __mutex_lock_common(lock, TASK_KILLABLE, subclass, NULL, _RET_IP_); > + return __mutex_lock_common(lock, TASK_KILLABLE, > + subclass, NULL, _RET_IP_, 0, 0); > } > EXPORT_SYMBOL_GPL(mutex_lock_killable_nested); > > @@ -294,10 +449,63 @@ mutex_lock_interruptible_nested(struct mutex *lock, unsigned int subclass) > { > might_sleep(); > return __mutex_lock_common(lock, TASK_INTERRUPTIBLE, > - subclass, NULL, _RET_IP_); > + subclass, NULL, _RET_IP_, 0, 0); > } > > EXPORT_SYMBOL_GPL(mutex_lock_interruptible_nested); > + > +int __sched > +_mutex_reserve_lock(struct ticket_mutex *lock, struct lockdep_map *nest, > + unsigned long reservation_id) > +{ > + DEBUG_LOCKS_WARN_ON(!reservation_id); > + > + might_sleep(); > + return __mutex_lock_common(&lock->base, TASK_UNINTERRUPTIBLE, > + 0, nest, _RET_IP_, reservation_id, 0); > +} > +EXPORT_SYMBOL_GPL(_mutex_reserve_lock); > + > + > +int __sched > +_mutex_reserve_lock_interruptible(struct ticket_mutex *lock, > + struct lockdep_map *nest, > + unsigned long reservation_id) > +{ > + DEBUG_LOCKS_WARN_ON(!reservation_id); > + > + might_sleep(); > + return __mutex_lock_common(&lock->base, TASK_INTERRUPTIBLE, > + 0, nest, _RET_IP_, reservation_id, 0); > +} > +EXPORT_SYMBOL_GPL(_mutex_reserve_lock_interruptible); > + > +void __sched > +_mutex_reserve_lock_slow(struct ticket_mutex *lock, struct lockdep_map *nest, > + unsigned long reservation_id) > +{ > + DEBUG_LOCKS_WARN_ON(!reservation_id); > + > + might_sleep(); > + __mutex_lock_common(&lock->base, TASK_UNINTERRUPTIBLE, 0, > + nest, _RET_IP_, reservation_id, 1); > +} > +EXPORT_SYMBOL_GPL(_mutex_reserve_lock_slow); > + > +int __sched > +_mutex_reserve_lock_intr_slow(struct ticket_mutex *lock, > + struct lockdep_map *nest, > + unsigned long reservation_id) > +{ > + DEBUG_LOCKS_WARN_ON(!reservation_id); > + > + might_sleep(); > + return __mutex_lock_common(&lock->base, TASK_INTERRUPTIBLE, 0, > + nest, _RET_IP_, reservation_id, 1); > +} > +EXPORT_SYMBOL_GPL(_mutex_reserve_lock_intr_slow); > + > + > #endif > > /* > @@ -400,7 +608,8 @@ __mutex_lock_slowpath(atomic_t *lock_count) > { > struct mutex *lock = container_of(lock_count, struct mutex, count); > > - __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, 0, NULL, _RET_IP_); > + __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, 0, > + NULL, _RET_IP_, 0, 0); > } > > static noinline int __sched > @@ -408,7 +617,8 @@ __mutex_lock_killable_slowpath(atomic_t *lock_count) > { > struct mutex *lock = container_of(lock_count, struct mutex, count); > > - return __mutex_lock_common(lock, TASK_KILLABLE, 0, NULL, _RET_IP_); > + return __mutex_lock_common(lock, TASK_KILLABLE, 0, > + NULL, _RET_IP_, 0, 0); > } > > static noinline int __sched > @@ -416,8 +626,28 @@ __mutex_lock_interruptible_slowpath(atomic_t *lock_count) > { > struct mutex *lock = container_of(lock_count, struct mutex, count); > > - return __mutex_lock_common(lock, TASK_INTERRUPTIBLE, 0, NULL, _RET_IP_); > + return __mutex_lock_common(lock, TASK_INTERRUPTIBLE, 0, > + NULL, _RET_IP_, 0, 0); > +} > + > +static noinline int __sched > +__mutex_lock_reserve_slowpath(atomic_t *lock_count, void *rid) > +{ > + struct mutex *lock = container_of(lock_count, struct mutex, count); > + > + return __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, 0, > + NULL, _RET_IP_, (unsigned long)rid, 0); > +} > + > +static noinline int __sched > +__mutex_lock_interruptible_reserve_slowpath(atomic_t *lock_count, void *rid) > +{ > + struct mutex *lock = container_of(lock_count, struct mutex, count); > + > + return __mutex_lock_common(lock, TASK_INTERRUPTIBLE, 0, > + NULL, _RET_IP_, (unsigned long)rid, 0); > } > + > #endif > > /* > @@ -473,6 +703,63 @@ int __sched mutex_trylock(struct mutex *lock) > } > EXPORT_SYMBOL(mutex_trylock); > > +#ifndef CONFIG_DEBUG_LOCK_ALLOC > +int __sched > +_mutex_reserve_lock(struct ticket_mutex *lock, unsigned long rid) > +{ > + int ret; > + > + might_sleep(); > + > + ret = __mutex_fastpath_lock_retval_arg(&lock->base.count, (void *)rid, > + __mutex_lock_reserve_slowpath); > + > + if (!ret) { > + mutex_set_reservation_fastpath(lock, rid, true); > + mutex_set_owner(&lock->base); > + } > + return ret; > +} > +EXPORT_SYMBOL(_mutex_reserve_lock); > + > +int __sched > +_mutex_reserve_lock_interruptible(struct ticket_mutex *lock, unsigned long rid) > +{ > + int ret; > + > + might_sleep(); > + > + ret = __mutex_fastpath_lock_retval_arg(&lock->base.count, (void *)rid, > + __mutex_lock_interruptible_reserve_slowpath); > + > + if (!ret) { > + mutex_set_reservation_fastpath(lock, rid, true); > + mutex_set_owner(&lock->base); > + } > + return ret; > +} > +EXPORT_SYMBOL(_mutex_reserve_lock_interruptible); > + > +void __sched > +_mutex_reserve_lock_slow(struct ticket_mutex *lock, unsigned long rid) > +{ > + might_sleep(); > + __mutex_lock_common(&lock->base, TASK_UNINTERRUPTIBLE, > + 0, NULL, _RET_IP_, rid, 1); > +} > +EXPORT_SYMBOL(_mutex_reserve_lock_slow); > + > +int __sched > +_mutex_reserve_lock_intr_slow(struct ticket_mutex *lock, unsigned long rid) > +{ > + might_sleep(); > + return __mutex_lock_common(&lock->base, TASK_INTERRUPTIBLE, > + 0, NULL, _RET_IP_, rid, 1); > +} > +EXPORT_SYMBOL(_mutex_reserve_lock_intr_slow); > + > +#endif > + > /** > * atomic_dec_and_mutex_lock - return holding mutex if we dec to 0 > * @cnt: the atomic which we are to dec _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel