diff options
Diffstat (limited to 'lib/rwsem-spinlock.c')
| -rw-r--r-- | lib/rwsem-spinlock.c | 38 | 
1 files changed, 16 insertions, 22 deletions
diff --git a/lib/rwsem-spinlock.c b/lib/rwsem-spinlock.c index 7542afbb22b..9be8a914497 100644 --- a/lib/rwsem-spinlock.c +++ b/lib/rwsem-spinlock.c @@ -9,12 +9,15 @@  #include <linux/sched.h>  #include <linux/export.h> +enum rwsem_waiter_type { +	RWSEM_WAITING_FOR_WRITE, +	RWSEM_WAITING_FOR_READ +}; +  struct rwsem_waiter {  	struct list_head list;  	struct task_struct *task; -	unsigned int flags; -#define RWSEM_WAITING_FOR_READ	0x00000001 -#define RWSEM_WAITING_FOR_WRITE	0x00000002 +	enum rwsem_waiter_type type;  };  int rwsem_is_locked(struct rw_semaphore *sem) @@ -67,26 +70,17 @@ __rwsem_do_wake(struct rw_semaphore *sem, int wakewrite)  	waiter = list_entry(sem->wait_list.next, struct rwsem_waiter, list); -	if (!wakewrite) { -		if (waiter->flags & RWSEM_WAITING_FOR_WRITE) -			goto out; -		goto dont_wake_writers; -	} - -	/* -	 * as we support write lock stealing, we can't set sem->activity -	 * to -1 here to indicate we get the lock. Instead, we wake it up -	 * to let it go get it again. -	 */ -	if (waiter->flags & RWSEM_WAITING_FOR_WRITE) { -		wake_up_process(waiter->task); +	if (waiter->type == RWSEM_WAITING_FOR_WRITE) { +		if (wakewrite) +			/* Wake up a writer. Note that we do not grant it the +			 * lock - it will have to acquire it when it runs. */ +			wake_up_process(waiter->task);  		goto out;  	}  	/* grant an infinite number of read locks to the front of the queue */ - dont_wake_writers:  	woken = 0; -	while (waiter->flags & RWSEM_WAITING_FOR_READ) { +	do {  		struct list_head *next = waiter->list.next;  		list_del(&waiter->list); @@ -96,10 +90,10 @@ __rwsem_do_wake(struct rw_semaphore *sem, int wakewrite)  		wake_up_process(tsk);  		put_task_struct(tsk);  		woken++; -		if (list_empty(&sem->wait_list)) +		if (next == &sem->wait_list)  			break;  		waiter = list_entry(next, struct rwsem_waiter, list); -	} +	} while (waiter->type != RWSEM_WAITING_FOR_WRITE);  	sem->activity += woken; @@ -144,7 +138,7 @@ void __sched __down_read(struct rw_semaphore *sem)  	/* set up my own style of waitqueue */  	waiter.task = tsk; -	waiter.flags = RWSEM_WAITING_FOR_READ; +	waiter.type = RWSEM_WAITING_FOR_READ;  	get_task_struct(tsk);  	list_add_tail(&waiter.list, &sem->wait_list); @@ -201,7 +195,7 @@ void __sched __down_write_nested(struct rw_semaphore *sem, int subclass)  	/* set up my own style of waitqueue */  	tsk = current;  	waiter.task = tsk; -	waiter.flags = RWSEM_WAITING_FOR_WRITE; +	waiter.type = RWSEM_WAITING_FOR_WRITE;  	list_add_tail(&waiter.list, &sem->wait_list);  	/* wait for someone to release the lock */  |