]> git.neil.brown.name Git - history.git/commitdiff
Be more careful about waking up rwsem waiters
authorLinus Torvalds <torvalds@ppc970.osdl.org>
Tue, 4 May 2004 05:30:47 +0000 (22:30 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Tue, 4 May 2004 05:30:47 +0000 (22:30 -0700)
Get a reference count on the the sleeper, so that
it can't possibly go away before we've sent it the
wakeup event.

Noted by Nick Piggin <nickpiggin@yahoo.com.au>
         David Howells <dhowells@redhat.com>

lib/rwsem-spinlock.c
lib/rwsem.c

index d6c0e14c272961c64f9f6b8455be50e15869cf1b..a71152d550f015b4847ffd9fb6fa525924420192 100644 (file)
@@ -71,10 +71,11 @@ static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem, int
        if (waiter->flags & RWSEM_WAITING_FOR_WRITE) {
                sem->activity = -1;
                list_del(&waiter->list);
-               mb();
                tsk = waiter->task;
+               mb();
                waiter->task = NULL;
                wake_up_process(tsk);
+               put_task_struct(tsk);
                goto out;
        }
 
@@ -85,10 +86,11 @@ static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem, int
                struct list_head *next = waiter->list.next;
 
                list_del(&waiter->list);
-               mb();
                tsk = waiter->task;
+               mb();
                waiter->task = NULL;
                wake_up_process(tsk);
+               put_task_struct(tsk);
                woken++;
                if (list_empty(&sem->wait_list))
                        break;
@@ -115,10 +117,11 @@ static inline struct rw_semaphore *__rwsem_wake_one_writer(struct rw_semaphore *
        waiter = list_entry(sem->wait_list.next,struct rwsem_waiter,list);
        list_del(&waiter->list);
 
-       mb();
        tsk = waiter->task;
+       mb();
        waiter->task = NULL;
        wake_up_process(tsk);
+       put_task_struct(tsk);
        return sem;
 }
 
@@ -147,6 +150,7 @@ void fastcall __down_read(struct rw_semaphore *sem)
        /* set up my own style of waitqueue */
        waiter.task = tsk;
        waiter.flags = RWSEM_WAITING_FOR_READ;
+       get_task_struct(tsk);
 
        list_add_tail(&waiter.list,&sem->wait_list);
 
@@ -215,6 +219,7 @@ void fastcall __down_write(struct rw_semaphore *sem)
        /* set up my own style of waitqueue */
        waiter.task = tsk;
        waiter.flags = RWSEM_WAITING_FOR_WRITE;
+       get_task_struct(tsk);
 
        list_add_tail(&waiter.list,&sem->wait_list);
 
index 7df79fdbe9ba7524172b79a684823ece89b6aaaa..ce15eb0137616d4fa1122825999f83835afcf2f8 100644 (file)
@@ -65,10 +65,11 @@ static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem, int
                goto readers_only;
 
        list_del(&waiter->list);
-       mb();
        tsk = waiter->task;
+       mb();
        waiter->task = NULL;
        wake_up_process(tsk);
+       put_task_struct(tsk);
        goto out;
 
        /* don't want to wake any writers */
@@ -102,10 +103,11 @@ static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem, int
        for (; loop>0; loop--) {
                waiter = list_entry(next,struct rwsem_waiter,list);
                next = waiter->list.next;
-               mb();
                tsk = waiter->task;
+               mb();
                waiter->task = NULL;
                wake_up_process(tsk);
+               put_task_struct(tsk);
        }
 
        sem->wait_list.next = next;
@@ -137,6 +139,7 @@ static inline struct rw_semaphore *rwsem_down_failed_common(struct rw_semaphore
        /* set up my own style of waitqueue */
        spin_lock(&sem->wait_lock);
        waiter->task = tsk;
+       get_task_struct(tsk);
 
        list_add_tail(&waiter->list,&sem->wait_list);