
From: Paul Jackson <pj@sgi.com>

Apply a couple of simplications to the cpuset_mems_generation mechanism
used to trigger a task into updating its mems_allowed when its cpuset
memory placement changes:

1) Didn't need tasklock, since only dealing with current task, and no
   one else is going to nuke current->cpuset out from under us.

2) Instead of dropping the cpuset semaphore cpuset_sem, and then jumping
   through flaming write-memory-barrier hoops to ensure that we didn't get
   an out of order generation number, rather pick off the current cpusets
   generation number while we have the cpuset locked anyway getting its
   nodemask.

The combination of the above allowed several fussy lines of code to go poof
into thin air.

Signed-off-by: Paul Jackson <pj@sgi.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/include/linux/cpuset.h |    6 -----
 25-akpm/kernel/cpuset.c        |   48 ++++++++---------------------------------
 2 files changed, 10 insertions(+), 44 deletions(-)

diff -puN include/linux/cpuset.h~cpusets-simplify-memory-generation include/linux/cpuset.h
--- 25/include/linux/cpuset.h~cpusets-simplify-memory-generation	Fri Sep 17 16:45:41 2004
+++ 25-akpm/include/linux/cpuset.h	Fri Sep 17 16:45:41 2004
@@ -19,7 +19,6 @@ extern void cpuset_init_smp(void);
 extern void cpuset_fork(struct task_struct *p);
 extern void cpuset_exit(struct task_struct *p);
 extern const cpumask_t cpuset_cpus_allowed(const struct task_struct *p);
-extern const nodemask_t cpuset_mems_allowed(const struct task_struct *p);
 void cpuset_init_current_mems_allowed(void);
 void cpuset_update_current_mems_allowed(void);
 void cpuset_restrict_to_mems_allowed(unsigned long *nodes);
@@ -40,11 +39,6 @@ static inline const cpumask_t cpuset_cpu
 	return cpu_possible_map;
 }
 
-static inline const nodemask_t cpuset_mems_allowed(struct task_struct *p)
-{
-	return node_possible_map;
-}
-
 static inline void cpuset_init_current_mems_allowed(void) {}
 static inline void cpuset_update_current_mems_allowed(void) {}
 static inline void cpuset_restrict_to_mems_allowed(unsigned long *nodes) {}
diff -puN kernel/cpuset.c~cpusets-simplify-memory-generation kernel/cpuset.c
--- 25/kernel/cpuset.c~cpusets-simplify-memory-generation	Fri Sep 17 16:45:41 2004
+++ 25-akpm/kernel/cpuset.c	Fri Sep 17 16:45:41 2004
@@ -555,7 +555,6 @@ static int update_nodemask(struct cpuset
 	if (retval == 0) {
 		cs->mems_allowed = trialcs.mems_allowed;
 		atomic_inc(&cpuset_mems_generation);
-		wmb();	/* insure above mems_allowed seen before next line */
 		cs->mems_generation = atomic_read(&cpuset_mems_generation);
 	}
 	return retval;
@@ -1199,7 +1198,6 @@ static long cpuset_create(struct cpuset 
 	INIT_LIST_HEAD(&cs->sibling);
 	INIT_LIST_HEAD(&cs->children);
 	atomic_inc(&cpuset_mems_generation);
-	wmb();	/* insure above mems_allowed seen before next line */
 	cs->mems_generation = atomic_read(&cpuset_mems_generation);
 
 	cs->parent = parent;
@@ -1379,53 +1377,27 @@ const cpumask_t cpuset_cpus_allowed(cons
 	return mask;
 }
 
-/**
- * cpuset_mems_allowed - return mems_allowed mask from a tasks cpuset.
- * @tsk: pointer to task_struct from which to obtain cpuset->mems_allowed.
- *
- * Description: Returns the nodemask_t mems_allowed of the cpuset
- * attached to the specified @tsk.
- **/
-
-const nodemask_t cpuset_mems_allowed(const struct task_struct *tsk)
-{
-	nodemask_t mask;
-
-	down(&cpuset_sem);
-	task_lock((struct task_struct *)tsk);
-	if (tsk->cpuset)
-		mask = tsk->cpuset->mems_allowed;
-	else
-		mask = NODE_MASK_ALL;
-	task_unlock((struct task_struct *)tsk);
-	up(&cpuset_sem);
-
-	return mask;
-}
-
 void cpuset_init_current_mems_allowed(void)
 {
 	current->mems_allowed = NODE_MASK_ALL;
 }
 
 /*
- * If the current tasks cpusets mems_allowed changes behind our backs,
- * update current->mems_allowed to the new value.  While loop for rare
- * race with concurrent cpuset changes.  Must insure that we never see
- * the next generation number with an old mems_allowed, in order to
- * avoid having stale mems_allowed w/o knowing it.  See also the wmb()
- * calls above.  Do not call this routine if in_interrupt().
+ * If the current tasks cpusets mems_allowed changed behind our backs,
+ * update current->mems_allowed and mems_generation to the new value.
+ * Do not call this routine if in_interrupt().
  */
 void cpuset_update_current_mems_allowed()
 {
-	int g;
+	struct cpuset *cs = current->cpuset;
 
-	if (!current->cpuset)
+	if (!cs)
 		return;		/* task is exiting */
-	while ((g = current->cpuset->mems_generation) !=
-					current->cpuset_mems_generation) {
-		current->mems_allowed = cpuset_mems_allowed(current);
-		current->cpuset_mems_generation = g;
+	if (current->cpuset_mems_generation != cs->mems_generation) {
+		down(&cpuset_sem);
+		current->mems_allowed = cs->mems_allowed;
+		current->cpuset_mems_generation = cs->mems_generation;
+		up(&cpuset_sem);
 	}
 }
 
_
