[PATCH] [ppc64] replace mmu_context_queue with idr allocator

Anton Blanchard anton at samba.org
Mon Sep 13 21:07:42 EST 2004


Replace the mmu_context_queue structure with the idr allocator. The
mmu_context_queue allocation was quite large (~200kB) so on most
machines we will have a reduction in usage.

We might put a single entry cache on the front of this so we are more
likely to reuse ppc64 MMU hashtable entries that are in the caches.

Signed-off-by: Anton Blanchard <anton at samba.org>

diff -puN arch/ppc64/mm/init.c~context_queue arch/ppc64/mm/init.c
--- 2.6.9-rc1-mm5/arch/ppc64/mm/init.c~context_queue	2004-09-13 19:51:26.130749817 +1000
+++ 2.6.9-rc1-mm5-anton/arch/ppc64/mm/init.c	2004-09-13 19:51:26.164747203 +1000
@@ -36,6 +36,7 @@
 #include <linux/delay.h>
 #include <linux/bootmem.h>
 #include <linux/highmem.h>
+#include <linux/idr.h>
 
 #include <asm/pgalloc.h>
 #include <asm/page.h>
@@ -62,8 +63,6 @@
 #include <asm/iommu.h>
 #include <asm/abs_addr.h>
 
-
-struct mmu_context_queue_t mmu_context_queue;
 int mem_init_done;
 unsigned long ioremap_bot = IMALLOC_BASE;
 static unsigned long phbs_io_bot = PHBS_IO_BASE;
@@ -477,6 +476,59 @@ void free_initrd_mem(unsigned long start
 }
 #endif
 
+static spinlock_t mmu_context_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_IDR(mmu_context_idr);
+
+int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+	int index;
+	int err;
+
+again:
+	if (!idr_pre_get(&mmu_context_idr, GFP_KERNEL))
+		return -ENOMEM;
+
+	spin_lock(&mmu_context_lock);
+	err = idr_get_new(&mmu_context_idr, NULL, &index);
+	spin_unlock(&mmu_context_lock);
+
+	if (err == -EAGAIN)
+		goto again;
+	else if (err)
+		return err;
+
+	if (index > MAX_CONTEXT) {
+		idr_remove(&mmu_context_idr, index);
+		return -ENOMEM;
+	}
+
+	mm->context.id = index;
+
+	return 0;
+}
+
+void destroy_context(struct mm_struct *mm)
+{
+	spin_lock(&mmu_context_lock);
+	idr_remove(&mmu_context_idr, mm->context.id);
+	spin_unlock(&mmu_context_lock);
+
+	mm->context.id = NO_CONTEXT;
+}
+
+static int __init mmu_context_init(void)
+{
+	int index;
+
+	/* Reserve the first (invalid) context*/
+	idr_pre_get(&mmu_context_idr, GFP_KERNEL);
+	idr_get_new(&mmu_context_idr, NULL, &index);
+	BUG_ON(0 != index);
+
+	return 0;
+}
+arch_initcall(mmu_context_init);
+
 /*
  * Do very early mm setup.
  */
@@ -486,17 +538,6 @@ void __init mm_init_ppc64(void)
 
 	ppc64_boot_msg(0x100, "MM Init");
 
-	/* Reserve all contexts < FIRST_USER_CONTEXT for kernel use.
-	 * The range of contexts [FIRST_USER_CONTEXT, NUM_USER_CONTEXT)
-	 * are stored on a stack/queue for easy allocation and deallocation.
-	 */
-	mmu_context_queue.lock = SPIN_LOCK_UNLOCKED;
-	mmu_context_queue.head = 0;
-	mmu_context_queue.tail = NUM_USER_CONTEXT-1;
-	mmu_context_queue.size = NUM_USER_CONTEXT;
-	for (i = 0; i < NUM_USER_CONTEXT; i++)
-		mmu_context_queue.elements[i] = i + FIRST_USER_CONTEXT;
-
 	/* This is the story of the IO hole... please, keep seated,
 	 * unfortunately, we are out of oxygen masks at the moment.
 	 * So we need some rough way to tell where your big IO hole
diff -puN include/asm-ppc64/mmu_context.h~context_queue include/asm-ppc64/mmu_context.h
--- 2.6.9-rc1-mm5/include/asm-ppc64/mmu_context.h~context_queue	2004-09-13 19:51:26.142748894 +1000
+++ 2.6.9-rc1-mm5-anton/include/asm-ppc64/mmu_context.h	2004-09-13 19:51:26.168746896 +1000
@@ -2,11 +2,9 @@
 #define __PPC64_MMU_CONTEXT_H
 
 #include <linux/config.h>
-#include <linux/spinlock.h>	
 #include <linux/kernel.h>	
 #include <linux/mm.h>	
 #include <asm/mmu.h>	
-#include <asm/ppcdebug.h>	
 #include <asm/cputable.h>
 
 /*
@@ -33,107 +31,15 @@ static inline int sched_find_first_bit(u
 	return __ffs(b[2]) + 128;
 }
 
-#define NO_CONTEXT		0
-#define FIRST_USER_CONTEXT	1
-#define LAST_USER_CONTEXT	0x8000  /* Same as PID_MAX for now... */
-#define NUM_USER_CONTEXT	(LAST_USER_CONTEXT-FIRST_USER_CONTEXT)
-
-/* Choose whether we want to implement our context
- * number allocator as a LIFO or FIFO queue.
- */
-#if 1
-#define MMU_CONTEXT_LIFO
-#else
-#define MMU_CONTEXT_FIFO
-#endif
-
-struct mmu_context_queue_t {
-	spinlock_t lock;
-	long head;
-	long tail;
-	long size;
-	mm_context_id_t elements[LAST_USER_CONTEXT];
-};
-
-extern struct mmu_context_queue_t mmu_context_queue;
-
-static inline void
-enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 }
 
-/*
- * The context number queue has underflowed.
- * Meaning: we tried to push a context number that was freed
- * back onto the context queue and the queue was already full.
- */
-static inline void
-mmu_context_underflow(void)
-{
-	printk(KERN_DEBUG "mmu_context_underflow\n");
-	panic("mmu_context_underflow");
-}
-
-/*
- * Set up the context for a new address space.
- */
-static inline int
-init_new_context(struct task_struct *tsk, struct mm_struct *mm)
-{
-	long head;
-	unsigned long flags;
-	/* This does the right thing across a fork (I hope) */
-
-	spin_lock_irqsave(&mmu_context_queue.lock, flags);
-
-	if (mmu_context_queue.size <= 0) {
-		spin_unlock_irqrestore(&mmu_context_queue.lock, flags);
-		return -ENOMEM;
-	}
+#define NO_CONTEXT	0
+#define MAX_CONTEXT	(0x100000-1)
 
-	head = mmu_context_queue.head;
-	mm->context.id = mmu_context_queue.elements[head];
-
-	head = (head < LAST_USER_CONTEXT-1) ? head+1 : 0;
-	mmu_context_queue.head = head;
-	mmu_context_queue.size--;
-
-	spin_unlock_irqrestore(&mmu_context_queue.lock, flags);
-
-	return 0;
-}
-
-/*
- * We're finished using the context for an address space.
- */
-static inline void
-destroy_context(struct mm_struct *mm)
-{
-	long index;
-	unsigned long flags;
-
-	spin_lock_irqsave(&mmu_context_queue.lock, flags);
-
-	if (mmu_context_queue.size >= NUM_USER_CONTEXT) {
-		spin_unlock_irqrestore(&mmu_context_queue.lock, flags);
-		mmu_context_underflow();
-	}
-
-#ifdef MMU_CONTEXT_LIFO
-	index = mmu_context_queue.head;
-	index = (index > 0) ? index-1 : LAST_USER_CONTEXT-1;
-	mmu_context_queue.head = index;
-#else
-	index = mmu_context_queue.tail;
-	index = (index < LAST_USER_CONTEXT-1) ? index+1 : 0;
-	mmu_context_queue.tail = index;
-#endif
-
-	mmu_context_queue.size++;
-	mmu_context_queue.elements[index] = mm->context.id;
-
-	spin_unlock_irqrestore(&mmu_context_queue.lock, flags);
-}
+extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
+extern void destroy_context(struct mm_struct *mm);
 
 extern void switch_stab(struct task_struct *tsk, struct mm_struct *mm);
 extern void switch_slb(struct task_struct *tsk, struct mm_struct *mm);
_



More information about the Linuxppc64-dev mailing list