[patch-2.3.99-pre7-2] nls_lock refinement

From: Tigran Aivazian (tigran@veritas.com)
Date: Wed May 03 2000 - 05:11:39 EST


Hi Linus,

As Al suggested:

Alexander Viro wrote:
> If anything, fs/nls/nls_base.c may be more worth it - same problem, same
> solution, same chance to use rwlocks and potentially longer list to deal
> with.

so I had a look and indeed it was in principle the same situation as with
file_systems but it was more worth it with file_systems because there are
explicit ways to traverse the list (sysfs(2) and /proc/filesystems) by
user action whilst for nls it seems we only traverse the list if we want
to load_nls() which means we would usually load a module and modify the
list and thus take a write lock. I.e. load_nls() would be:

find_nls() - take a read nls_lock
request_module() - take a write nls_lock in register_nls()
find_nls() - take a read nls_lock

So, the only saving is ability to execute 1st and 3rd parts of that code
concurrently but the middle is still serialized because of
register_nls() taking nls_lock for write.

Nevertheless, I promoted nls_lock from being a plain spinlock to being a
rw spinlock - better a little improvement than none at all.

Regards,
Tigran

--- fs/nls/nls_base.c.0 Wed May 3 10:55:05 2000
+++ fs/nls/nls_base.c Wed May 3 10:57:41 2000
@@ -21,7 +21,7 @@
 #include <asm/byteorder.h>
 
 static struct nls_table *tables = (struct nls_table *) NULL;
-static spinlock_t nls_lock = SPIN_LOCK_UNLOCKED;
+static rwlock_t nls_lock = RW_LOCK_UNLOCKED;
 
 /*
  * Sample implementation from Unicode home page.
@@ -168,17 +168,17 @@
         if (nls->next)
                 return -EBUSY;
 
- spin_lock(&nls_lock);
+ write_lock(&nls_lock);
         while (*tmp) {
                 if (nls == *tmp) {
- spin_unlock(&nls_lock);
+ write_unlock(&nls_lock);
                         return -EBUSY;
                 }
                 tmp = &(*tmp)->next;
         }
         nls->next = tables;
         tables = nls;
- spin_unlock(&nls_lock);
+ write_unlock(&nls_lock);
         return 0;
 }
 
@@ -186,29 +186,29 @@
 {
         struct nls_table ** tmp = &tables;
 
- spin_lock(&nls_lock);
+ write_lock(&nls_lock);
         while (*tmp) {
                 if (nls == *tmp) {
                         *tmp = nls->next;
- spin_unlock(&nls_lock);
+ write_unlock(&nls_lock);
                         return 0;
                 }
                 tmp = &(*tmp)->next;
         }
- spin_unlock(&nls_lock);
+ write_unlock(&nls_lock);
         return -EINVAL;
 }
 
 static struct nls_table *find_nls(char *charset)
 {
         struct nls_table *nls;
- spin_lock(&nls_lock);
+ read_lock(&nls_lock);
         for (nls = tables; nls; nls = nls->next)
                 if (! strcmp(nls->charset, charset))
                         break;
         if (nls && !try_inc_mod_count(nls->owner))
                 nls = NULL;
- spin_unlock(&nls_lock);
+ read_unlock(&nls_lock);
         return nls;
 }
 

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sun May 07 2000 - 21:00:11 EST