Messages in this thread Patch in this message | | | Date | Sun, 25 Sep 2005 18:03:45 +1000 | From | Nick Piggin <> | Subject | Re: [PATCH linux-2.6 01/04] brsem: implement big reader semaphore |
| |
Nick Piggin wrote:
> What would be wrong with an array of NR_CPUS rwsems? The only > tiny trick you would have to do AFAIKS is have up_read remember > what rwsem down_read took, but that could be returned from > down_read as a token.
Here's something to start with. Add initialisers / cacheline alignment / percpu_alloc to taste.
For bonus points I guess you could change the implementation to just a single waitqueue mechanism with NR_CPUs counters.
In fact, it probably needs quite a bit of work before it is mainline-worthy, but as a proof of concept - do you see anything wrong with it?
Nick
-- SUSE Labs, Novell Inc.
Index: linux-2.6/include/linux/brsem.h =================================================================== --- /dev/null +++ linux-2.6/include/linux/brsem.h @@ -0,0 +1,18 @@ +#ifndef __BRSEM_H +#define __BRSEM_H + +#include <linux/rwsem.h> +struct brsem { + struct rw_semaphore cpu_sem[NR_CPUS]; +}; + +#define BRSEM_READ_TRYLOCK_FAILED -1 +typedef int brsem_read_t; + +brsem_read_t brsem_down_read(struct brsem *); +brsem_read_t brsem_down_read_trylock(struct brsem *); +void brsem_up_read(struct brsem *, brsem_read_t); +void brsem_down_write(struct brsem *); +void brsem_up_write(struct brsem *); + +#endif Index: linux-2.6/lib/Makefile =================================================================== --- linux-2.6.orig/lib/Makefile +++ linux-2.6/lib/Makefile @@ -5,7 +5,7 @@ lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \ bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \ idr.o div64.o int_sqrt.o bitmap.o extable.o prio_tree.o \ - sha1.o + sha1.o brsem.o lib-y += kobject.o kref.o kobject_uevent.o klist.o Index: linux-2.6/lib/brsem.c =================================================================== --- /dev/null +++ linux-2.6/lib/brsem.c @@ -0,0 +1,38 @@ +#include <linux/brsem.h> +#include <linux/rwsem.h> +#include <linux/smp.h> + +brsem_read_t brsem_down_read(struct brsem *brsem) +{ + brsem_read_t ret = smp_processor_id(); + down_read(&brsem->cpu_sem[ret]); + return ret; +} + +brsem_read_t brsem_down_read_trylock(struct brsem *brsem) +{ + brsem_read_t ret = smp_processor_id(); + if (!down_read_trylock(&brsem->cpu_sem[ret])) + return BRSEM_READ_TRYLOCK_FAILED; + return ret; +} + +void brsem_up_read(struct brsem *brsem, brsem_read_t token) +{ + up_read(&brsem->cpu_sem[token]); +} + +void brsem_down_write(struct brsem *brsem) +{ + int i; + for (i = 0; i < NR_CPUS; i++) + down_write(&brsem->cpu_sem[i]); +} + +void brsem_up_write(struct brsem *brsem) +{ + int i; + for (i = 0; i < NR_CPUS; i++) + up_write(&brsem->cpu_sem[i]); +} + | |