public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] Align VM locks, new spinlock patch
@ 2001-09-21 13:15 Juergen Doelle
  2001-09-22 23:07 ` Andrew Morton
  2001-09-24 14:02 ` Stephen C. Tweedie
  0 siblings, 2 replies; 5+ messages in thread
From: Juergen Doelle @ 2001-09-21 13:15 UTC (permalink / raw)
  To: Andrea Arcangeli
  Cc: Andrew Morton, linux-kernel, Mark Hemment, lse-tech, Steve Fox

Andrea Arcangeli wrote:

> On Thu, Aug 16, 2001 at 12:14:23PM -0700, Andrew Morton wrote:
> > Problem with this approach is that it doesn't prevent the linker
> > from placing other data in the same cacheline as the aligned
> > lock, at higher addresses.
> 
> that was partly intentional, but ok we can be more aggressive on that
> side ;).
> 
> > Juergen, I'd suggest you dust off that patch, add the conditionals
> > which make it a no-op on uniprocessor and submit it.  It's such a
> 
> agreed, btw it is just a noop on up but it is undefined for __GNUC__ >
> 2, also it would be nice if he could do it in linux/ instead of asm/, it
> should not need special arch trick (spinlock_t and SMP_CACHE_SIZE are
> the only thing it needs).


Sorry, it tooks some time, because of my vacation and then the disk drive
I used for testing gets damaged.

I changed the spinlock patch according to your suggestions. 

Description
-----------

The patch introduces a new type spinlock_cacheline_t which 
o aligns the spinlock to a cacheline and 
o avoids that this spinlock shares the cacheline with other data
This type is now hardware independent.

It declares following spinlocks from type spinlock_cacheline_t:
o kmap_lock         
o pagecache_lock    
o pagemap_lru_lock  
o lru_list_lock     
o kernel_flag  
Where the kernel_flag is modified only for i386 architecture, because
the spinlock itself is hardware dependent implemented. 

I tested the patch on 2.4.5, 2.4.8, and 2.4.10-pre7. 
Kernel 2.4.10-pre7 requires a separate version of the patch, because 
the pagecache_lock and the lru_list_lock are already aligned.


The peak throughput results with dbench:

    2.4.10  2.4.10 +        improvement 
            spinlock patch  by patch    

 U  103.77  102.14          - 1.6%
 1   96.82   96.77          - 0.1%
 2  155.32  155.62            0.2%
 4  209.45  222.11            6.0%
 8  208.06  234.82           12.9%

The improvement is less than in previous posted results, because the 
pagemap_lru_lock and the lru_list_lock are already cacheline aligned
in 2.4.10 (2.4.9).

I attached two versions of the patch, one which applies for 2.4.x-2.4.8
and below a version for 2.4.10 (heading: Spinlock patch for kernel 2.4.10),
which applies also to 2.4.9, but I didn't test it.

Juergen 

______________________________________________________________
Juergen Doelle
IBM Linux Technology Center - kernel performance
jdoelle@de.ibm.com




= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Spinlock patch for kernel 2.4.x-2.4.8
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

--- linux/include/asm-i386/smplock.h.orig	Thu Sep  6 14:46:25 2001
+++ linux/include/asm-i386/smplock.h	Thu Sep  6 16:38:02 2001
@@ -8,7 +8,13 @@
 #include <linux/sched.h>
 #include <asm/current.h>
 
-extern spinlock_t kernel_flag;
+
+#ifdef CONFIG_SMP
+    extern spinlock_cacheline_t kernel_flag_cacheline; 
+    #define kernel_flag kernel_flag_cacheline.lock     
+#else
+    extern spinlock_t kernel_flag;
+#endif
 
 #define kernel_locked()		spin_is_locked(&kernel_flag)
 
--- linux/arch/i386/kernel/i386_ksyms.c.orig	Thu Sep  6 16:00:29 2001
+++ linux/arch/i386/kernel/i386_ksyms.c	Thu Sep  6 16:03:07 2001
@@ -120,7 +120,7 @@
 
 #ifdef CONFIG_SMP
 EXPORT_SYMBOL(cpu_data);
-EXPORT_SYMBOL(kernel_flag);
+EXPORT_SYMBOL(kernel_flag_cacheline);
 EXPORT_SYMBOL(smp_num_cpus);
 EXPORT_SYMBOL(cpu_online_map);
 EXPORT_SYMBOL_NOVERS(__write_lock_failed);
--- linux/include/linux/spinlock.h.orig	Thu Sep  6 14:30:41 2001
+++ linux/include/linux/spinlock.h	Thu Sep  6 16:38:02 2001
@@ -34,6 +34,13 @@
 #ifdef CONFIG_SMP
 #include <asm/spinlock.h>
 
+#include <linux/cache.h>
+typedef union {                                                    
+    spinlock_t lock;                                               
+    char fill_up[(SMP_CACHE_BYTES)];                               
+} spinlock_cacheline_t __attribute__ ((aligned(SMP_CACHE_BYTES))); 
+                                                                   
+
 #elif !defined(spin_lock_init) /* !SMP and spin_lock_init not previously
                                   defined (e.g. by including asm/spinlock.h */
 
--- linux/include/linux/swap.h.orig	Thu Sep  6 14:38:01 2001
+++ linux/include/linux/swap.h	Thu Sep  6 16:38:02 2001
@@ -88,7 +88,13 @@
 extern struct address_space swapper_space;
 extern atomic_t page_cache_size;
 extern atomic_t buffermem_pages;
-extern spinlock_t pagecache_lock;
+#ifdef CONFIG_SMP
+    extern spinlock_cacheline_t pagecache_lock_cacheline;  
+    #define pagecache_lock (pagecache_lock_cacheline.lock) 
+#else
+    extern spinlock_t pagecache_lock;
+#endif
+
 extern void __remove_inode_page(struct page *);
 
 /* Incomplete types for prototype declarations: */
@@ -179,7 +185,12 @@
 extern unsigned long swap_cache_find_success;
 #endif
 
-extern spinlock_t pagemap_lru_lock;
+#ifdef CONFIG_SMP
+    extern spinlock_cacheline_t pagemap_lru_lock_cacheline;  
+    #define pagemap_lru_lock pagemap_lru_lock_cacheline.lock 
+#else
+    extern spinlock_t pagemap_lru_lock;
+#endif
 
 /*
  * Page aging defines.
--- linux/fs/buffer.c.orig	Thu Sep  6 15:10:07 2001
+++ linux/fs/buffer.c	Thu Sep  6 15:54:00 2001
@@ -83,13 +83,22 @@
 static rwlock_t hash_table_lock = RW_LOCK_UNLOCKED;
 
 static struct buffer_head *lru_list[NR_LIST];
-static spinlock_t lru_list_lock = SPIN_LOCK_UNLOCKED;
+
+#ifdef CONFIG_SMP
+    static spinlock_cacheline_t lru_list_lock_cacheline = {SPIN_LOCK_UNLOCKED}; 
+    #ifndef lru_list_lock                                                       
+        #define lru_list_lock  lru_list_lock_cacheline.lock                       
+    #endif                                                                      
+#else
+    static spinlock_t lru_list_lock = SPIN_LOCK_UNLOCKED;    
+#endif
 static int nr_buffers_type[NR_LIST];
 static unsigned long size_buffers_type[NR_LIST];
 
 static struct buffer_head * unused_list;
 static int nr_unused_buffer_heads;
 static spinlock_t unused_list_lock = SPIN_LOCK_UNLOCKED;
+
 static DECLARE_WAIT_QUEUE_HEAD(buffer_wait);
 
 struct bh_free_head {
--- linux/mm/filemap.c.orig	Thu Sep  6 14:55:44 2001
+++ linux/mm/filemap.c	Thu Sep  6 15:06:21 2001
@@ -45,12 +45,28 @@
 unsigned int page_hash_bits;
 struct page **page_hash_table;
 
-spinlock_t pagecache_lock = SPIN_LOCK_UNLOCKED;
+#ifdef CONFIG_SMP
+    spinlock_cacheline_t pagecache_lock_cacheline  = {SPIN_LOCK_UNLOCKED};  
+    #ifndef pagecache_lock                                                  
+        #define pagecache_lock  pagecache_lock_cacheline.lock                 
+    #endif                                                                  
+#else
+    spinlock_t pagecache_lock = SPIN_LOCK_UNLOCKED;
+#endif
+
 /*
  * NOTE: to avoid deadlocking you must never acquire the pagecache_lock with
  *       the pagemap_lru_lock held.
  */
-spinlock_t pagemap_lru_lock = SPIN_LOCK_UNLOCKED;
+#ifdef CONFIG_SMP
+    spinlock_cacheline_t pagemap_lru_lock_cacheline = {SPIN_LOCK_UNLOCKED};  
+    #ifndef pagemap_lru_lock                                                 
+        #define pagemap_lru_lock  pagemap_lru_lock_cacheline.lock             
+    #endif                                                                   
+#else
+    spinlock_t pagemap_lru_lock = SPIN_LOCK_UNLOCKED;
+#endif
+
 
 #define CLUSTER_PAGES		(1 << page_cluster)
 #define CLUSTER_OFFSET(x)	(((x) >> page_cluster) << page_cluster)
--- linux/mm/highmem.c.orig	Thu Sep  6 14:55:54 2001
+++ linux/mm/highmem.c	Thu Sep  6 15:08:22 2001
@@ -32,7 +32,14 @@
  */
 static int pkmap_count[LAST_PKMAP];
 static unsigned int last_pkmap_nr;
-static spinlock_t kmap_lock = SPIN_LOCK_UNLOCKED;
+#ifdef CONFIG_SMP
+    static spinlock_cacheline_t kmap_lock_cacheline = {SPIN_LOCK_UNLOCKED}; 
+    #ifndef kmap_lock                                                       
+        #define kmap_lock  kmap_lock_cacheline.lock                           
+    #endif                                                                  
+#else
+    static spinlock_t kmap_lock = SPIN_LOCK_UNLOCKED;
+#endif
 
 pte_t * pkmap_page_table;
 
--- linux/arch/i386/kernel/smp.c.orig	Thu Sep  6 14:52:01 2001
+++ linux/arch/i386/kernel/smp.c	Thu Sep  6 16:04:38 2001
@@ -101,7 +101,14 @@
  */
 
 /* The 'big kernel lock' */
+#ifdef CONFIG_SMP
+    spinlock_cacheline_t kernel_flag_cacheline = {SPIN_LOCK_UNLOCKED}; 
+    #ifndef kernel_flag                                                
+        #define kernel_flag  kernel_flag_cacheline.lock                  
+    #endif
+#else                                              
 spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+#endif
 
 struct tlb_state cpu_tlbstate[NR_CPUS] = {[0 ... NR_CPUS-1] = { &init_mm, 0 }};
 

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Spinlock patch for kernel 2.4.10 (2.4.9)
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

--- linux/include/asm-i386/smplock.h.orig	Thu Sep  6 14:46:25 2001
+++ linux/include/asm-i386/smplock.h	Thu Sep  6 16:38:02 2001
@@ -8,7 +8,13 @@
 #include <linux/sched.h>
 #include <asm/current.h>
 
-extern spinlock_t kernel_flag;
+
+#ifdef CONFIG_SMP
+    extern spinlock_cacheline_t kernel_flag_cacheline; 
+    #define kernel_flag kernel_flag_cacheline.lock     
+#else
+    extern spinlock_t kernel_flag;
+#endif
 
 #define kernel_locked()		spin_is_locked(&kernel_flag)
 
--- linux/arch/i386/kernel/i386_ksyms.c.orig	Thu Sep  6 16:00:29 2001
+++ linux/arch/i386/kernel/i386_ksyms.c	Thu Sep  6 16:03:07 2001
@@ -120,7 +120,7 @@
 
 #ifdef CONFIG_SMP
 EXPORT_SYMBOL(cpu_data);
-EXPORT_SYMBOL(kernel_flag);
+EXPORT_SYMBOL(kernel_flag_cacheline);
 EXPORT_SYMBOL(smp_num_cpus);
 EXPORT_SYMBOL(cpu_online_map);
 EXPORT_SYMBOL_NOVERS(__write_lock_failed);
--- linux/include/linux/spinlock.h.orig	Thu Sep  6 14:30:41 2001
+++ linux/include/linux/spinlock.h	Thu Sep  6 16:38:02 2001
@@ -34,6 +34,13 @@
 #ifdef CONFIG_SMP
 #include <asm/spinlock.h>
 
+#include <linux/cache.h>
+typedef union {                                                    
+    spinlock_t lock;                                               
+    char fill_up[(SMP_CACHE_BYTES)];                               
+} spinlock_cacheline_t __attribute__ ((aligned(SMP_CACHE_BYTES))); 
+                                                                   
+
 #elif !defined(spin_lock_init) /* !SMP and spin_lock_init not previously
                                   defined (e.g. by including asm/spinlock.h */
 
--- linux/include/linux/swap.h.orig	Thu Sep  6 14:38:01 2001
+++ linux/include/linux/swap.h	Thu Sep  6 16:38:02 2001
@@ -88,7 +88,13 @@
 extern struct address_space swapper_space;
 extern atomic_t page_cache_size;
 extern atomic_t buffermem_pages;
-extern spinlock_t pagecache_lock;
+#ifdef CONFIG_SMP
+    extern spinlock_cacheline_t pagecache_lock_cacheline;  
+    #define pagecache_lock (pagecache_lock_cacheline.lock) 
+#else
+    extern spinlock_t pagecache_lock;
+#endif
+
 extern void __remove_inode_page(struct page *);
 
 /* Incomplete types for prototype declarations: */
@@ -179,7 +185,12 @@
 extern unsigned long swap_cache_find_success;
 #endif
 
-extern spinlock_t pagemap_lru_lock;
+#ifdef CONFIG_SMP
+    extern spinlock_cacheline_t pagemap_lru_lock_cacheline;  
+    #define pagemap_lru_lock pagemap_lru_lock_cacheline.lock 
+#else
+    extern spinlock_t pagemap_lru_lock;
+#endif
 
 /*
  * Page aging defines.
--- linux/fs/buffer.c.orig	Thu Sep  6 15:10:07 2001
+++ linux/fs/buffer.c	Thu Sep  6 15:54:00 2001
@@ -83,13 +83,22 @@
 static rwlock_t hash_table_lock = RW_LOCK_UNLOCKED;
 
 static struct buffer_head *lru_list[NR_LIST];
-static spinlock_t lru_list_lock = SPIN_LOCK_UNLOCKED;
+
+#ifdef CONFIG_SMP
+    static spinlock_cacheline_t lru_list_lock_cacheline = {SPIN_LOCK_UNLOCKED}; 
+    #ifndef lru_list_lock                                                       
+        #define lru_list_lock  lru_list_lock_cacheline.lock                       
+    #endif                                                                      
+#else
+    static spinlock_t lru_list_lock = SPIN_LOCK_UNLOCKED;    
+#endif
 static int nr_buffers_type[NR_LIST];
 static unsigned long size_buffers_type[NR_LIST];
 
 static struct buffer_head * unused_list;
 static int nr_unused_buffer_heads;
 static spinlock_t unused_list_lock = SPIN_LOCK_UNLOCKED;
+
 static DECLARE_WAIT_QUEUE_HEAD(buffer_wait);
 
 struct bh_free_head {
--- linux/mm/filemap.c.orig	Thu Sep  6 14:55:44 2001
+++ linux/mm/filemap.c	Thu Sep  6 15:06:21 2001
@@ -45,12 +45,28 @@
 unsigned int page_hash_bits;
 struct page **page_hash_table;
 
-spinlock_t __cacheline_aligned pagecache_lock = SPIN_LOCK_UNLOCKED;
+#ifdef CONFIG_SMP
+    spinlock_cacheline_t pagecache_lock_cacheline  = {SPIN_LOCK_UNLOCKED};  
+    #ifndef pagecache_lock                                                  
+        #define pagecache_lock  pagecache_lock_cacheline.lock                 
+    #endif                                                                  
+#else
+    spinlock_t pagecache_lock = SPIN_LOCK_UNLOCKED;
+#endif
+
 /*
  * NOTE: to avoid deadlocking you must never acquire the pagecache_lock with
  *       the pagemap_lru_lock held.
  */
-spinlock_t __cacheline_aligned pagemap_lru_lock = SPIN_LOCK_UNLOCKED;
+#ifdef CONFIG_SMP
+    spinlock_cacheline_t pagemap_lru_lock_cacheline = {SPIN_LOCK_UNLOCKED};  
+    #ifndef pagemap_lru_lock                                                 
+        #define pagemap_lru_lock  pagemap_lru_lock_cacheline.lock             
+    #endif                                                                   
+#else
+    spinlock_t pagemap_lru_lock = SPIN_LOCK_UNLOCKED;
+#endif
+
 
 #define CLUSTER_PAGES		(1 << page_cluster)
 #define CLUSTER_OFFSET(x)	(((x) >> page_cluster) << page_cluster)
--- linux/mm/highmem.c.orig	Thu Sep  6 14:55:54 2001
+++ linux/mm/highmem.c	Thu Sep  6 15:08:22 2001
@@ -32,7 +32,14 @@
  */
 static int pkmap_count[LAST_PKMAP];
 static unsigned int last_pkmap_nr;
-static spinlock_t kmap_lock = SPIN_LOCK_UNLOCKED;
+#ifdef CONFIG_SMP
+    static spinlock_cacheline_t kmap_lock_cacheline = {SPIN_LOCK_UNLOCKED}; 
+    #ifndef kmap_lock                                                       
+        #define kmap_lock  kmap_lock_cacheline.lock                           
+    #endif                                                                  
+#else
+    static spinlock_t kmap_lock = SPIN_LOCK_UNLOCKED;
+#endif
 
 pte_t * pkmap_page_table;
 
--- linux/arch/i386/kernel/smp.c.orig	Thu Sep  6 14:52:01 2001
+++ linux/arch/i386/kernel/smp.c	Thu Sep  6 16:04:38 2001
@@ -101,7 +101,14 @@
  */
 
 /* The 'big kernel lock' */
+#ifdef CONFIG_SMP
+    spinlock_cacheline_t kernel_flag_cacheline = {SPIN_LOCK_UNLOCKED}; 
+    #ifndef kernel_flag                                                
+        #define kernel_flag  kernel_flag_cacheline.lock                  
+    #endif
+#else                                                             
 spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+#endif
 
 struct tlb_state cpu_tlbstate[NR_CPUS] = {[0 ... NR_CPUS-1] = { &init_mm, 0 }};

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Align VM locks, new spinlock patch
  2001-09-21 13:15 Juergen Doelle
@ 2001-09-22 23:07 ` Andrew Morton
  2001-09-24 14:02 ` Stephen C. Tweedie
  1 sibling, 0 replies; 5+ messages in thread
From: Andrew Morton @ 2001-09-22 23:07 UTC (permalink / raw)
  To: Juergen Doelle
  Cc: Andrea Arcangeli, linux-kernel, Mark Hemment, lse-tech, Steve Fox

Juergen Doelle wrote:
> 
> ...
> The patch introduces a new type spinlock_cacheline_t which
> o aligns the spinlock to a cacheline and
> o avoids that this spinlock shares the cacheline with other data
> This type is now hardware independent.
> 
> It declares following spinlocks from type spinlock_cacheline_t:
> o kmap_lock
> o pagecache_lock
> o pagemap_lru_lock
> o lru_list_lock
> o kernel_flag
> Where the kernel_flag is modified only for i386 architecture, because
> the spinlock itself is hardware dependent implemented.
> 
> I tested the patch on 2.4.5, 2.4.8, and 2.4.10-pre7.
> Kernel 2.4.10-pre7 requires a separate version of the patch, because
> the pagecache_lock and the lru_list_lock are already aligned.
> 
> The peak throughput results with dbench:
> 
>     2.4.10  2.4.10 +        improvement
>             spinlock patch  by patch
> 
>  U  103.77  102.14          - 1.6%
>  1   96.82   96.77          - 0.1%
>  2  155.32  155.62            0.2%
>  4  209.45  222.11            6.0%
>  8  208.06  234.82           12.9%
> 

I guess the uniprocessor case is measurement error - spin_lock()
is a no-op on UP.

I think the coding can be simplified somewhat.  How does this
look?



--- linux-2.4.10-pre14/include/linux/spinlock.h	Mon Jul 30 20:55:14 2001
+++ linux-akpm/include/linux/spinlock.h	Sat Sep 22 14:15:25 2001
@@ -133,4 +133,20 @@ typedef struct {
 extern int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock);
 #endif
 
+#ifdef CONFIG_SMP
+#include <linux/cache.h>
+
+typedef union {                                                    
+    spinlock_t lock;                                               
+    char fill_up[(SMP_CACHE_BYTES)];                               
+} spinlock_cacheline_t __attribute__ ((aligned(SMP_CACHE_BYTES)));
+
+#else	/* SMP */
+
+typedef struct {                                                    
+    spinlock_t lock;                                               
+} spinlock_cacheline_t;
+
+
+#endif
 #endif /* __LINUX_SPINLOCK_H */
--- linux-2.4.10-pre14/include/linux/swap.h	Sat Sep 22 13:58:05 2001
+++ linux-akpm/include/linux/swap.h	Sat Sep 22 14:15:25 2001
@@ -87,7 +87,10 @@ extern atomic_t nr_async_pages;
 extern struct address_space swapper_space;
 extern atomic_t page_cache_size;
 extern atomic_t buffermem_pages;
-extern spinlock_t pagecache_lock;
+
+extern spinlock_cacheline_t pagecache_lock_cacheline;  
+#define pagecache_lock (pagecache_lock_cacheline.lock) 
+
 extern void __remove_inode_page(struct page *);
 
 /* Incomplete types for prototype declarations: */
@@ -168,7 +171,8 @@ extern unsigned long swap_cache_find_tot
 extern unsigned long swap_cache_find_success;
 #endif
 
-extern spinlock_t pagemap_lru_lock;
+extern spinlock_cacheline_t pagemap_lru_lock_cacheline;  
+#define pagemap_lru_lock pagemap_lru_lock_cacheline.lock 
 
 extern void FASTCALL(mark_page_accessed(struct page *));
 
--- linux-2.4.10-pre14/arch/i386/kernel/i386_ksyms.c	Sat Sep 22 13:57:52 2001
+++ linux-akpm/arch/i386/kernel/i386_ksyms.c	Sat Sep 22 13:42:22 2001
@@ -120,7 +120,7 @@ EXPORT_SYMBOL(mmx_copy_page);
 
 #ifdef CONFIG_SMP
 EXPORT_SYMBOL(cpu_data);
-EXPORT_SYMBOL(kernel_flag);
+EXPORT_SYMBOL(kernel_flag_cacheline);
 EXPORT_SYMBOL(smp_num_cpus);
 EXPORT_SYMBOL(cpu_online_map);
 EXPORT_SYMBOL_NOVERS(__write_lock_failed);
--- linux-2.4.10-pre14/arch/i386/kernel/smp.c	Sat Sep 22 13:57:52 2001
+++ linux-akpm/arch/i386/kernel/smp.c	Sat Sep 22 13:42:22 2001
@@ -101,7 +101,7 @@
  */
 
 /* The 'big kernel lock' */
-spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+spinlock_cacheline_t kernel_flag_cacheline = {SPIN_LOCK_UNLOCKED}; 
 
 struct tlb_state cpu_tlbstate[NR_CPUS] = {[0 ... NR_CPUS-1] = { &init_mm, 0 }};
 
--- linux-2.4.10-pre14/fs/buffer.c	Sat Sep 22 13:58:00 2001
+++ linux-akpm/fs/buffer.c	Sat Sep 22 13:42:22 2001
@@ -81,13 +81,17 @@ static struct buffer_head **hash_table;
 static rwlock_t hash_table_lock = RW_LOCK_UNLOCKED;
 
 static struct buffer_head *lru_list[NR_LIST];
-static spinlock_t lru_list_lock = SPIN_LOCK_UNLOCKED;
+
+static spinlock_cacheline_t lru_list_lock_cacheline = {SPIN_LOCK_UNLOCKED}; 
+#define lru_list_lock  lru_list_lock_cacheline.lock                       
+
 static int nr_buffers_type[NR_LIST];
 static unsigned long size_buffers_type[NR_LIST];
 
 static struct buffer_head * unused_list;
 static int nr_unused_buffer_heads;
 static spinlock_t unused_list_lock = SPIN_LOCK_UNLOCKED;
+
 static DECLARE_WAIT_QUEUE_HEAD(buffer_wait);
 
 struct bh_free_head {
--- linux-2.4.10-pre14/mm/filemap.c	Sat Sep 22 13:58:05 2001
+++ linux-akpm/mm/filemap.c	Sat Sep 22 13:42:22 2001
@@ -46,12 +46,13 @@ atomic_t page_cache_size = ATOMIC_INIT(0
 unsigned int page_hash_bits;
 struct page **page_hash_table;
 
-spinlock_t pagecache_lock ____cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
+spinlock_cacheline_t pagecache_lock_cacheline  = {SPIN_LOCK_UNLOCKED};  
+
 /*
  * NOTE: to avoid deadlocking you must never acquire the pagecache_lock with
  *       the pagemap_lru_lock held.
  */
-spinlock_t pagemap_lru_lock ____cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
+spinlock_cacheline_t pagemap_lru_lock_cacheline = {SPIN_LOCK_UNLOCKED};  
 
 #define CLUSTER_PAGES		(1 << page_cluster)
 #define CLUSTER_OFFSET(x)	(((x) >> page_cluster) << page_cluster)
--- linux-2.4.10-pre14/mm/highmem.c	Sat Sep 22 13:58:05 2001
+++ linux-akpm/mm/highmem.c	Sat Sep 22 13:42:22 2001
@@ -32,7 +32,7 @@
  */
 static int pkmap_count[LAST_PKMAP];
 static unsigned int last_pkmap_nr;
-static spinlock_t kmap_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_cacheline_t kmap_lock_cacheline = {SPIN_LOCK_UNLOCKED}; 
 
 pte_t * pkmap_page_table;

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Align VM locks, new spinlock patch
  2001-09-21 13:15 Juergen Doelle
  2001-09-22 23:07 ` Andrew Morton
@ 2001-09-24 14:02 ` Stephen C. Tweedie
  1 sibling, 0 replies; 5+ messages in thread
From: Stephen C. Tweedie @ 2001-09-24 14:02 UTC (permalink / raw)
  To: Juergen Doelle
  Cc: Andrea Arcangeli, Andrew Morton, linux-kernel, Mark Hemment,
	lse-tech, Steve Fox, Stephen Tweedie

Hi,

On Fri, Sep 21, 2001 at 03:15:17PM +0200, Juergen Doelle wrote:

>     2.4.10  2.4.10 +        improvement 
>             spinlock patch  by patch    
> 
>  U  103.77  102.14          - 1.6%
>  1   96.82   96.77          - 0.1%
>  2  155.32  155.62            0.2%
>  4  209.45  222.11            6.0%
>  8  208.06  234.82           12.9%
> 
> The improvement is less than in previous posted results, because the 
> pagemap_lru_lock and the lru_list_lock are already cacheline aligned
> in 2.4.10 (2.4.9).

Do you have CPU utilisation differences for these cases, as well as
pure IO bandwidth differences?  It would be interesting to see just
how much the IO code's internal latency impacts on the final dbench
numbers.

--Stephen

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Align VM locks, new spinlock patch
@ 2001-09-26 15:15 Juergen Doelle
  0 siblings, 0 replies; 5+ messages in thread
From: Juergen Doelle @ 2001-09-26 15:15 UTC (permalink / raw)
  To: Stephen Tweedie, Andrea Arcangeli, Andrew Morton, linux-kernel,
	Mark Hemment, lse-tech, Steve Fox


Stephen C. Tweedie wrote
> Do you have CPU utilisation differences for these cases, as well as
> pure IO bandwidth differences?  It would be interesting to see just
> how much the IO code's internal latency impacts on the final dbench
> numbers.

I created vmstat traces for dbench 22

+-----------------------------------+------------------------------+
| 2.4.10                            | 2.4.10 + spinlock patch      |                                  
+----+----------+-------+-----------+----------+-------+-----------+                       
|time|procs     |  IO   | cpu       |procs     |  IO   | cpu       |      
+    +----------+-------+-----------+----------+-------+-----------+ 
|[s] | r  b   w |  bo/s | us  sy id | r  b   w |  bo/s | us  sy id |    
+----+----------+-------+-----------+----------+-------+-----------+ 
|  1 | 23  0  0 |     0 |  0  14 85 | 22  0  0 |     0 |  1  47 52 |    
|  2 | 22  0  0 |     0 |  2  98  0 | 22  0  0 |     0 |  2  99  0 |     
|  3 | 22  0  0 |     0 |  2  98  0 | 22  0  0 |     0 |  4  97  0 |     
|  4 |  8 14  2 | 11052 | 12  89  0 |  5 17  1 | 20465 | 11  84  5 |     
|  5 |  3 19  1 |  1616 |  1   4 94 | 20  2  6 |  1788 | 16  83  0 |    
|  6 |  1 21  1 |  1760 |  2   4 94 | 22  0  4 |     0 | 18  82  0 |    
|  7 | 23  0  3 |  2852 | 12  46 42 | 22  0  1 |     0 | 19  80  0 |    
|  8 | 22  0  3 |     0 | 15  85  0 | 22  0  0 |     0 | 19  82  0 |     
|  9 | 22  0  2 |     0 | 17  83  0 | 23  0  0 |     0 | 18  82  0 |     
| 10 | 23  0  1 |     0 | 16  84  0 | 22  0  0 |     0 | 17  82  1 |     
| 11 | 22  0  0 |     0 | 14  86  0 | 22  0  0 |     0 | 18  83    |     
| 12 | 22  0  0 |     0 | 16  84  0 | 19  0  0 |     0 | 18  82  0 |     
| 13 | 22  0  0 |     0 | 19  81  1 |  9  0  0 |     0 |  7  94    |     
| 14 | 20  0  0 |     0 | 17  84  0 |  0  0  0 |     0 |  0  30 70 |     
| 15 | 17  0  0 |     0 | 15  85  0 |----------+-------+-----------+     
| 16 | 13  0  0 |     0 |  4  97  0 |      
| 17 | 12  0  0 |     0 |  0 100  0 |      
| 18 |  7  0  0 |     0 |  0  99  0 |      
| 19 |  0  0  0 |     0 |  0  15 85 |     
+----+----------+-------+-----------+
*the empty idle columns originally containing 5315553, treat as '0'

The patch 
o reduces significantly the idle times, the user process wait time
  is much shorter
o reduces the I/O phase to the  half of the time, by much higher rates
o increases the user and decreases the system CPU utilization 

I prior posted lockmeter results on 2.4.5, where this patch reduced 
for 8 CPUs the average spin hold time by about 47% and the total CPU 
utilization spent for spinning by 45%. 
I think it does not influence the device layer directly. It speeds up 
the time spent in critical phases protected with spin locks, when the
number of competitors increases. In case of high competitions caused by
many parallel working processors, the buffer cache and pagecache 
handling gets faster and this increases the number of changed pages per 
second.

Therefore the mechanism used here can also be used to improve 
competitive scenarios for other spin locks.


Juergen

______________________________________________________________
Juergen Doelle
IBM Linux Technology Center - kernel performance
jdoelle@de.ibm.com

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Align VM locks, new spinlock patch
@ 2001-09-26 15:15 Juergen Doelle
  0 siblings, 0 replies; 5+ messages in thread
From: Juergen Doelle @ 2001-09-26 15:15 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andrea Arcangeli, linux-kernel, linux-kernel-owner, lse-tech,
	Mark Hemment, Steve Fox, Alan Cox

Andrew Morton wrote:
> I think the coding can be simplified somewhat.  How does this
> look?
> ...

Looks fine, it makes the code more common between UP and SMP. 
I consolidated the changes and appended the new version below.


The peak throughput results (MB/sec) for dbench on 2.4.10:

CPU 2.4.10  2.4.10 +        improvement 
            spinlock patch  by patch    

 U  102,9   103,0          0,0%
 1   95,1    96,9          1,9%
 2  155,5   156,0          0,3%
 4  206,9   222,1          7,3%
 8  194,9   233,7         19,9%

Throughput (MB/sec) for dbench with 8 clients on 8 CPUs:
CPU 2.4.10  2.4.10 +        improvement 
            spinlock patch  by patch    
 8  173,9   223,0            28,2%


Juergen

______________________________________________________________
Juergen Doelle
IBM Linux Technology Center - kernel performance
jdoelle@de.ibm.com


= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

--- linux/include/linux/spinlock.h.orig	Tue Sep 25 09:05:09 2001
+++ linux/include/linux/spinlock.h	Tue Sep 25 11:42:51 2001
@@ -133,4 +133,20 @@
 extern int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock);
 #endif
 
+#ifdef CONFIG_SMP
+#include <linux/cache.h>
+
+typedef union {
+    spinlock_t lock;
+    char fill_up[(SMP_CACHE_BYTES)];
+} spinlock_cacheline_t __attribute__ ((aligned(SMP_CACHE_BYTES)));
+
+#else	/* SMP */
+
+typedef struct {
+    spinlock_t lock;
+} spinlock_cacheline_t;
+
+
+#endif
 #endif /* __LINUX_SPINLOCK_H */
--- linux/include/linux/swap.h.orig	Tue Sep 25 09:59:15 2001
+++ linux/include/linux/swap.h	Tue Sep 25 11:42:51 2001
@@ -86,7 +86,10 @@
 extern atomic_t nr_async_pages;
 extern atomic_t page_cache_size;
 extern atomic_t buffermem_pages;
-extern spinlock_t pagecache_lock;
+
+extern spinlock_cacheline_t pagecache_lock_cacheline;
+#define pagecache_lock (pagecache_lock_cacheline.lock)
+
 extern void __remove_inode_page(struct page *);
 
 /* Incomplete types for prototype declarations: */
@@ -159,7 +162,8 @@
 extern unsigned long swap_cache_find_success;
 #endif
 
-extern spinlock_t pagemap_lru_lock;
+extern spinlock_cacheline_t pagemap_lru_lock_cacheline;
+#define pagemap_lru_lock pagemap_lru_lock_cacheline.lock
 
 extern void FASTCALL(mark_page_accessed(struct page *));
 
--- linux/include/asm-i386/smplock.h.orig	Tue Sep 25 11:29:51 2001
+++ linux/include/asm-i386/smplock.h	Tue Sep 25 11:42:52 2001
@@ -8,7 +8,8 @@
 #include <linux/sched.h>
 #include <asm/current.h>
 
-extern spinlock_t kernel_flag;
+extern spinlock_cacheline_t kernel_flag_cacheline;  
+#define kernel_flag kernel_flag_cacheline.lock      
 
 #define kernel_locked()		spin_is_locked(&kernel_flag)
 
--- linux/arch/i386/kernel/i386_ksyms.c.orig	Tue Sep 25 09:14:57 2001
+++ linux/arch/i386/kernel/i386_ksyms.c	Tue Sep 25 10:13:06 2001
@@ -120,7 +120,7 @@
 
 #ifdef CONFIG_SMP
 EXPORT_SYMBOL(cpu_data);
-EXPORT_SYMBOL(kernel_flag);
+EXPORT_SYMBOL(kernel_flag_cacheline);
 EXPORT_SYMBOL(smp_num_cpus);
 EXPORT_SYMBOL(cpu_online_map);
 EXPORT_SYMBOL_NOVERS(__write_lock_failed);
--- linux/arch/i386/kernel/smp.c.orig	Tue Sep 25 09:15:16 2001
+++ linux/arch/i386/kernel/smp.c	Tue Sep 25 10:13:06 2001
@@ -101,7 +101,7 @@
  */
 
 /* The 'big kernel lock' */
-spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+spinlock_cacheline_t kernel_flag_cacheline = {SPIN_LOCK_UNLOCKED};
 
 struct tlb_state cpu_tlbstate[NR_CPUS] = {[0 ... NR_CPUS-1] = { &init_mm, 0 }};
 
--- linux/fs/buffer.c.orig	Tue Sep 25 09:15:47 2001
+++ linux/fs/buffer.c	Wed Sep 26 12:17:29 2001
@@ -81,7 +81,10 @@
 static rwlock_t hash_table_lock = RW_LOCK_UNLOCKED;
 
 static struct buffer_head *lru_list[NR_LIST];
-static spinlock_t lru_list_lock = SPIN_LOCK_UNLOCKED;
+
+static spinlock_cacheline_t lru_list_lock_cacheline = {SPIN_LOCK_UNLOCKED};
+#define lru_list_lock  lru_list_lock_cacheline.lock
+
 static int nr_buffers_type[NR_LIST];
 static unsigned long size_buffers_type[NR_LIST];
 
--- linux/mm/filemap.c.orig	Tue Sep 25 09:16:06 2001
+++ linux/mm/filemap.c	Tue Sep 25 10:13:06 2001
@@ -46,12 +46,13 @@
 unsigned int page_hash_bits;
 struct page **page_hash_table;
 
-spinlock_t pagecache_lock ____cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
+spinlock_cacheline_t pagecache_lock_cacheline  = {SPIN_LOCK_UNLOCKED};
+
 /*
  * NOTE: to avoid deadlocking you must never acquire the pagecache_lock with
  *       the pagemap_lru_lock held.
  */
-spinlock_t pagemap_lru_lock ____cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
+spinlock_cacheline_t pagemap_lru_lock_cacheline = {SPIN_LOCK_UNLOCKED};
 
 #define CLUSTER_PAGES		(1 << page_cluster)
 #define CLUSTER_OFFSET(x)	(((x) >> page_cluster) << page_cluster)
--- linux/mm/highmem.c.orig	Tue Sep 25 09:29:49 2001
+++ linux/mm/highmem.c	Tue Sep 25 10:21:14 2001
@@ -32,7 +32,8 @@
  */
 static int pkmap_count[LAST_PKMAP];
 static unsigned int last_pkmap_nr;
-static spinlock_t kmap_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_cacheline_t kmap_lock_cacheline = {SPIN_LOCK_UNLOCKED};
+#define kmap_lock  kmap_lock_cacheline.lock
 
 pte_t * pkmap_page_table;

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2001-09-26 15:18 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-09-26 15:15 [PATCH] Align VM locks, new spinlock patch Juergen Doelle
  -- strict thread matches above, loose matches on Subject: below --
2001-09-26 15:15 Juergen Doelle
2001-09-21 13:15 Juergen Doelle
2001-09-22 23:07 ` Andrew Morton
2001-09-24 14:02 ` Stephen C. Tweedie

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox