patch-2.4.27 linux-2.4.27/lib/rwsem-spinlock.c

Next file: linux-2.4.27/lib/rwsem.c
Previous file: linux-2.4.27/kernel/sysctl.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.26/lib/rwsem-spinlock.c linux-2.4.27/lib/rwsem-spinlock.c
@@ -9,6 +9,7 @@
  */
 #include <linux/rwsem.h>
 #include <linux/sched.h>
+#include <linux/mm.h>
 #include <linux/module.h>
 
 struct rwsem_waiter {
@@ -52,6 +53,7 @@
 static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem)
 {
 	struct rwsem_waiter *waiter;
+	struct task_struct *tsk;
 	int woken;
 
 	rwsemtrace(sem,"Entering __rwsem_do_wake");
@@ -64,8 +66,11 @@
 	if (waiter->flags & RWSEM_WAITING_FOR_WRITE) {
 		sem->activity = -1;
 		list_del(&waiter->list);
-		waiter->flags = 0;
-		wake_up_process(waiter->task);
+		tsk = waiter->task;
+		mb();
+		waiter->task = NULL;
+		wake_up_process(tsk);
+		free_task_struct(tsk);
 		goto out;
 	}
 
@@ -73,8 +78,11 @@
 	woken = 0;
 	do {
 		list_del(&waiter->list);
-		waiter->flags = 0;
-		wake_up_process(waiter->task);
+		tsk = waiter->task;
+		mb();
+		waiter->task = NULL;
+		wake_up_process(tsk);
+		free_task_struct(tsk);
 		woken++;
 		if (list_empty(&sem->wait_list))
 			break;
@@ -94,14 +102,18 @@
 static inline struct rw_semaphore *__rwsem_wake_one_writer(struct rw_semaphore *sem)
 {
 	struct rwsem_waiter *waiter;
+	struct task_struct *tsk;
 
 	sem->activity = -1;
 
 	waiter = list_entry(sem->wait_list.next,struct rwsem_waiter,list);
 	list_del(&waiter->list);
 
-	waiter->flags = 0;
-	wake_up_process(waiter->task);
+	tsk = waiter->task;
+	mb();
+	waiter->task = NULL;
+	wake_up_process(tsk);
+	free_task_struct(tsk);
 	return sem;
 }
 
@@ -130,6 +142,7 @@
 	/* 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);
 
@@ -138,7 +151,7 @@
 
 	/* wait to be given the lock */
 	for (;;) {
-		if (!waiter.flags)
+		if (!waiter.task)
 			break;
 		schedule();
 		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
@@ -198,6 +211,7 @@
 	/* 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);
 
@@ -206,7 +220,7 @@
 
 	/* wait to be given the lock */
 	for (;;) {
-		if (!waiter.flags)
+		if (!waiter.task)
 			break;
 		schedule();
 		set_task_state(tsk, TASK_UNINTERRUPTIBLE);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)