Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id ; Tue, 11 Feb 2003 13:50:44 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id ; Tue, 11 Feb 2003 13:50:44 -0500 Received: from [213.86.99.237] ([213.86.99.237]:26603 "EHLO warthog.cambridge.redhat.com") by vger.kernel.org with ESMTP id ; Tue, 11 Feb 2003 13:50:16 -0500 To: "Chen, Kenneth W" cc: linux-kernel@vger.kernel.org, andrea@suse.de, dhowells@redhat.com Subject: Re: rwsem-rw bench In-Reply-To: <51568623CC066847A1DC7EB0D95B587AF82D72@fmsmsx405.fm.intel.com> User-Agent: EMH/1.14.1 SEMI/1.14.4 (Hosorogi) FLIM/1.14.4 (=?ISO-8859-4?Q?Kashiharajing=FE-mae?=) APEL/10.4 Emacs/21.2 (i386-redhat-linux-gnu) MULE/5.0 (SAKAKI) MIME-Version: 1.0 (generated by SEMI 1.14.4 - "Hosorogi") Content-Type: text/plain; charset=US-ASCII Date: Tue, 11 Feb 2003 18:59:44 +0000 Message-ID: <512.1044989984@warthog.cambridge.redhat.com> From: David Howells Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 35683 Lines: 1448 Here you go... SHAR format though. Have fun. David #!/bin/sh # This is a shell archive (produced by GNU sharutils 4.2.1). # To extract the files from this archive, save it to some FILE, remove # everything before the `!/bin/sh' line above, then type `sh FILE'. # # Made on 2003-02-11 18:58 GMT by . # Source directory was `/dhowells/rwsem-tests'. # # Existing files will *not* be overwritten unless `-c' is specified. # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 722 -rw-r--r-- driver.c # 568 -rw-r--r-- Makefile # 2745 -rw-r--r-- rwsem.c # 2391 -rw-r--r-- rwsem-r1.c # 2427 -rw-r--r-- rwsem-r2.c # 2499 -rw-r--r-- rwsem-ro.c # 3179 -rw-r--r-- rwsem-rw.c # 2619 -rw-r--r-- rwsem-stat.txt # 2467 -rw-r--r-- rwsem-w1.c # 2578 -rw-r--r-- rwsem-wo.c # 345 -rw-r--r-- wibble.c # save_IFS="${IFS}" IFS="${IFS}:" gettext_dir=FAILED locale_dir=FAILED first_param="$1" for dir in $PATH do if test "$gettext_dir" = FAILED && test -f $dir/gettext \ && ($dir/gettext --version >/dev/null 2>&1) then set `$dir/gettext --version 2>&1` if test "$3" = GNU then gettext_dir=$dir fi fi if test "$locale_dir" = FAILED && test -f $dir/shar \ && ($dir/shar --print-text-domain-dir >/dev/null 2>&1) then locale_dir=`$dir/shar --print-text-domain-dir` fi done IFS="$save_IFS" if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED then echo=echo else TEXTDOMAINDIR=$locale_dir export TEXTDOMAINDIR TEXTDOMAIN=sharutils export TEXTDOMAIN echo="$gettext_dir/gettext -s" fi if touch -am -t 200112312359.59 $$.touch >/dev/null 2>&1 && test ! -f 200112312359.59 -a -f $$.touch; then shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"' elif touch -am 123123592001.59 $$.touch >/dev/null 2>&1 && test ! -f 123123592001.59 -a ! -f 123123592001.5 -a -f $$.touch; then shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"' elif touch -am 1231235901 $$.touch >/dev/null 2>&1 && test ! -f 1231235901 -a -f $$.touch; then shar_touch='touch -am $3$4$5$6$2 "$8"' else shar_touch=: echo $echo 'WARNING: not restoring timestamps. Consider getting and' $echo "installing GNU \`touch', distributed in GNU File Utilities..." echo fi rm -f 200112312359.59 123123592001.59 123123592001.5 1231235901 $$.touch # if mkdir _sh00477; then $echo 'x -' 'creating lock directory' else $echo 'failed to create lock directory' exit 1 fi # ============= driver.c ============== if test -f 'driver.c' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'driver.c' '(file already exists)' else $echo 'x -' extracting 'driver.c' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'driver.c' && /* run.c: run rwsem test X * X * Copyright (c) 2001 David Howells (dhowells@redhat.com). X */ #include #include #include #include #include X int main(int argc, char *argv[]) { X char buf[1]; X int max, loop, fd, tmp, rw; X X fd = open("/proc/rwsem",O_RDWR); X if (fd<0) { X perror("open"); X return 1; X } X X max = (argc>1) ? atoi(argv[1]) : 50; X rw = max<0; X max = abs(max); X X for (loop=max; loop>0; loop--) { X switch (fork()) { X case -1: X perror("fork"); X return 1; X case 0: X rw ? write(fd," ",1) : read(fd,buf,1); X exit(1); X default: X break; X } X } X X for (loop=max; loop>0; loop--) { X if (wait(&tmp)<0) { X perror("wait"); X return 1; X } X } X X return 0; } SHAR_EOF (set 20 01 04 10 18 17 09 'driver.c'; eval "$shar_touch") && chmod 0644 'driver.c' || $echo 'restore of' 'driver.c' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'driver.c:' 'MD5 check failed' d1fa721cb13209319829801d8e5f9947 driver.c SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'driver.c'`" test 722 -eq "$shar_count" || $echo 'driver.c:' 'original size' '722,' 'current size' "$shar_count!" fi fi # ============= Makefile ============== if test -f 'Makefile' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'Makefile' '(file already exists)' else $echo 'x -' extracting 'Makefile' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'Makefile' && ############################################################ # # # ############################################################ X CFLAGS := -Wall -Wstrict-prototypes -D__KERNEL__ -DMODULE CFLAGS += -pipe -O2 -fomit-frame-pointer -fno-strict-aliasing CFLAGS += -march=i686 -mpreferred-stack-boundary=2 CFLAGS += -I /dhowells/linux-rwsem/include X ifdef SCHED CFLAGS += -DSCHED endif X all: driver \ X rwsem.o \ X rwsem-rw.o \ X rwsem-ro.o \ X rwsem-wo.o \ X rwsem-r1.o \ X rwsem-w1.o \ X rwsem-r2.o \ X wibble.o X clean: X rm -f *.o *~ driver X %.s: %.c X $(CC) $(CFLAGS) -S -o $@ $< SHAR_EOF (set 20 01 04 20 13 02 27 'Makefile'; eval "$shar_touch") && chmod 0644 'Makefile' || $echo 'restore of' 'Makefile' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'Makefile:' 'MD5 check failed' 30fcf0375e03f36310239d6b38123c91 Makefile SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'Makefile'`" test 568 -eq "$shar_count" || $echo 'Makefile:' 'original size' '568,' 'current size' "$shar_count!" fi fi # ============= rwsem.c ============== if test -f 'rwsem.c' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'rwsem.c' '(file already exists)' else $echo 'x -' extracting 'rwsem.c' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'rwsem.c' && /* rwsem.c: bad R/W semaphore support X * X * Copyright (c) 2001 David Howells (dhowells@redhat.com). X */ X #define __NO_VERSION__ #include #include #include #include #include #include #include #include #include X #define kdebug(FMT,...) //#define kdebug printk X MODULE_AUTHOR("David Howells"); MODULE_DESCRIPTION("R/W semaphore test demo"); X X struct proc_dir_entry *rwsem_proc; X struct rw_semaphore rwsem_sem; X #define SLEEP(sec) { \ int slsec = sec; \ X while (slsec) { \ X current->state = TASK_INTERRUPTIBLE; \ X schedule_timeout(HZ); \ X slsec--; \ X current->state = TASK_RUNNING; \ X } \ } X /*****************************************************************************/ /* X * X */ static int rwsem_read_proc(char *page, char **start, off_t off, X int count, int *eof, void *data) { X kdebug("[%d] r-downing: %08x\n",current->pid,rwsem_sem.count.counter); X down_read(&rwsem_sem); X kdebug("[%d] r-downed: %08x\n",current->pid,rwsem_sem.count.counter); X SLEEP(1); X kdebug("[%d] r-upping: %08x\n",current->pid,rwsem_sem.count.counter); X up_read(&rwsem_sem); X kdebug("[%d] r-upped: %08x\n",current->pid,rwsem_sem.count.counter); X X return -ENOENT; } /* end rwsem_read_proc() */ X /*****************************************************************************/ /* X * X */ static int rwsem_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) { X kdebug("[%d] w-downing: %08x\n",current->pid,rwsem_sem.count.counter); X down_write(&rwsem_sem); X kdebug("[%d] w-downed: %08x\n",current->pid,rwsem_sem.count.counter); X SLEEP(1); X kdebug("[%d] w-upping: %08x\n",current->pid,rwsem_sem.count.counter); X up_write(&rwsem_sem); X kdebug("[%d] w-upped: %08x\n",current->pid,rwsem_sem.count.counter); X X return -ENOENT; } /* end rwsem_write_proc() */ X /*****************************************************************************/ /* X * X */ static int __init rwsem_init_module(void) { X kdebug(KERN_INFO "rwsem loading...\n"); X X init_rwsem(&rwsem_sem); X X //rwsem_sem.debug = 1; X X /* try and create the access point */ X rwsem_proc = create_proc_entry("rwsem",S_IRUGO|S_IWUGO,NULL); X if (!rwsem_proc) X return -EEXIST; X X rwsem_proc->read_proc = &rwsem_read_proc; X rwsem_proc->write_proc = &rwsem_write_proc; X return 0; } /* end rwsem_init_module() */ X /*****************************************************************************/ /* X * X */ static void __exit rwsem_cleanup_module(void) { X kdebug(KERN_INFO "rwsem unloading\n"); X X remove_proc_entry("rwsem",NULL); X } /* end rwsem_cleanup_module() */ X module_init(rwsem_init_module); module_exit(rwsem_cleanup_module); SHAR_EOF (set 20 01 04 12 15 11 27 'rwsem.c'; eval "$shar_touch") && chmod 0644 'rwsem.c' || $echo 'restore of' 'rwsem.c' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'rwsem.c:' 'MD5 check failed' b54bbebf12f0319ef756d47d3ad6f817 rwsem.c SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'rwsem.c'`" test 2745 -eq "$shar_count" || $echo 'rwsem.c:' 'original size' '2745,' 'current size' "$shar_count!" fi fi # ============= rwsem-r1.c ============== if test -f 'rwsem-r1.c' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'rwsem-r1.c' '(file already exists)' else $echo 'x -' extracting 'rwsem-r1.c' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'rwsem-r1.c' && /* X * This is for the new, simple rwsems X */ X #define __NO_VERSION__ #include #include #include #include #include #include #include #include #include #include #include X struct rw_semaphore rwsem_sem; X #ifdef DEBUG_RWSEM extern struct rw_semaphore *rwsem_to_monitor; #endif X static atomic_t readers = ATOMIC_INIT(0); static atomic_t writers = ATOMIC_INIT(0); static atomic_t do_stuff = ATOMIC_INIT(0); static atomic_t runners = ATOMIC_INIT(0); static atomic_t reads_taken = ATOMIC_INIT(0); static atomic_t writes_taken = ATOMIC_INIT(0); X static struct timer_list timer; X #define CHECK(expr) \ X do { \ X if (!(expr)) { \ X printk("check " #expr " failed in " __FUNCTION__ "\n");\ X } \ X } while (0) X static inline void dr(void) { X down_read(&rwsem_sem); X atomic_inc(&readers); X atomic_inc(&reads_taken); X CHECK(atomic_read(&writers) == 0); } X static inline void ur(void) { X CHECK(atomic_read(&writers) == 0); X atomic_dec(&readers); X up_read(&rwsem_sem); } X static inline void sched(void) { #ifdef SCHED X schedule(); #endif } X int reader(void *arg) { X strcpy(current->comm, arg); X current->mm->arg_start = 0; X current->mm->arg_end = 0; X X atomic_inc(&runners); X X while (atomic_read(&do_stuff)) { X dr(); X ur(); X sched(); X } X X atomic_dec(&runners); X printk("%s: done\n",current->comm); X return 0; } X static void stop_test(unsigned long dummy) { X atomic_set(&do_stuff, 0); } X static int __init rwsem_init_module(void) { X printk(KERN_INFO "rwsem loading...\n"); X X init_rwsem(&rwsem_sem); X atomic_set(&do_stuff, 1); X #ifdef DEBUG_RWSEM X rwsem_to_monitor = &rwsem_sem; #endif X init_timer(&timer); X timer.function = stop_test; X timer.expires = jiffies + 5 * HZ; X add_timer(&timer); X X kernel_thread(reader, "ReadA", 0); X X return 0; } X static void __exit rwsem_cleanup_module(void) { X printk(KERN_INFO "rwsem unloading\n"); X X atomic_set(&do_stuff, 0); X del_timer(&timer); X while (atomic_read(&runners)) X schedule(); X printk("reads taken: %d\n", atomic_read(&reads_taken)); X printk("writes taken: %d\n", atomic_read(&writes_taken)); #ifdef DEBUG_RWSEM X rwsem_to_monitor = 0; #endif X remove_proc_entry("rwsem",NULL); X } X module_init(rwsem_init_module); module_exit(rwsem_cleanup_module); SHAR_EOF (set 20 01 04 19 21 37 06 'rwsem-r1.c'; eval "$shar_touch") && chmod 0644 'rwsem-r1.c' || $echo 'restore of' 'rwsem-r1.c' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'rwsem-r1.c:' 'MD5 check failed' 7316246a6b3e829c4ccb45a957161036 rwsem-r1.c SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'rwsem-r1.c'`" test 2391 -eq "$shar_count" || $echo 'rwsem-r1.c:' 'original size' '2391,' 'current size' "$shar_count!" fi fi # ============= rwsem-r2.c ============== if test -f 'rwsem-r2.c' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'rwsem-r2.c' '(file already exists)' else $echo 'x -' extracting 'rwsem-r2.c' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'rwsem-r2.c' && /* X * This is for the new, simple rwsems X */ X #define __NO_VERSION__ #include #include #include #include #include #include #include #include #include #include #include X struct rw_semaphore rwsem_sem; X #ifdef DEBUG_RWSEM extern struct rw_semaphore *rwsem_to_monitor; #endif X static atomic_t readers = ATOMIC_INIT(0); static atomic_t writers = ATOMIC_INIT(0); static atomic_t do_stuff = ATOMIC_INIT(0); static atomic_t runners = ATOMIC_INIT(0); static atomic_t reads_taken = ATOMIC_INIT(0); static atomic_t writes_taken = ATOMIC_INIT(0); X static struct timer_list timer; X #define CHECK(expr) \ X do { \ X if (!(expr)) { \ X printk("check " #expr " failed in " __FUNCTION__ "\n");\ X } \ X } while (0) X static inline void dr(void) { X down_read(&rwsem_sem); X atomic_inc(&readers); X atomic_inc(&reads_taken); X CHECK(atomic_read(&writers) == 0); } X static inline void ur(void) { X CHECK(atomic_read(&writers) == 0); X atomic_dec(&readers); X up_read(&rwsem_sem); } X static inline void sched(void) { #ifdef SCHED X schedule(); #endif } X int reader(void *arg) { X strcpy(current->comm, arg); X current->mm->arg_start = 0; X current->mm->arg_end = 0; X X atomic_inc(&runners); X X while (atomic_read(&do_stuff)) { X dr(); X ur(); X sched(); X } X X atomic_dec(&runners); X printk("%s: done\n",current->comm); X return 0; } X static void stop_test(unsigned long dummy) { X atomic_set(&do_stuff, 0); } X static int __init rwsem_init_module(void) { X printk(KERN_INFO "rwsem loading...\n"); X X init_rwsem(&rwsem_sem); X atomic_set(&do_stuff, 1); X #ifdef DEBUG_RWSEM X rwsem_to_monitor = &rwsem_sem; #endif X init_timer(&timer); X timer.function = stop_test; X timer.expires = jiffies + 5 * HZ; X add_timer(&timer); X X kernel_thread(reader, "ReadA", 0); X kernel_thread(reader, "ReadB", 0); X X return 0; } X static void __exit rwsem_cleanup_module(void) { X printk(KERN_INFO "rwsem unloading\n"); X X atomic_set(&do_stuff, 0); X del_timer(&timer); X while (atomic_read(&runners)) X schedule(); X printk("reads taken: %d\n", atomic_read(&reads_taken)); X printk("writes taken: %d\n", atomic_read(&writes_taken)); #ifdef DEBUG_RWSEM X rwsem_to_monitor = 0; #endif X remove_proc_entry("rwsem",NULL); X } X module_init(rwsem_init_module); module_exit(rwsem_cleanup_module); SHAR_EOF (set 20 01 04 19 22 01 38 'rwsem-r2.c'; eval "$shar_touch") && chmod 0644 'rwsem-r2.c' || $echo 'restore of' 'rwsem-r2.c' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'rwsem-r2.c:' 'MD5 check failed' c22df6923bf7bb928fc163646ea3438a rwsem-r2.c SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'rwsem-r2.c'`" test 2427 -eq "$shar_count" || $echo 'rwsem-r2.c:' 'original size' '2427,' 'current size' "$shar_count!" fi fi # ============= rwsem-ro.c ============== if test -f 'rwsem-ro.c' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'rwsem-ro.c' '(file already exists)' else $echo 'x -' extracting 'rwsem-ro.c' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'rwsem-ro.c' && /* X * This is for the new, simple rwsems X */ X #define __NO_VERSION__ #include #include #include #include #include #include #include #include #include #include #include X struct rw_semaphore rwsem_sem; X #ifdef DEBUG_RWSEM extern struct rw_semaphore *rwsem_to_monitor; #endif X static atomic_t readers = ATOMIC_INIT(0); static atomic_t writers = ATOMIC_INIT(0); static atomic_t do_stuff = ATOMIC_INIT(0); static atomic_t runners = ATOMIC_INIT(0); static atomic_t reads_taken = ATOMIC_INIT(0); static atomic_t writes_taken = ATOMIC_INIT(0); X static struct timer_list timer; X #define CHECK(expr) \ X do { \ X if (!(expr)) { \ X printk("check " #expr " failed in " __FUNCTION__ "\n");\ X } \ X } while (0) X static inline void dr(void) { X down_read(&rwsem_sem); X atomic_inc(&readers); X atomic_inc(&reads_taken); X CHECK(atomic_read(&writers) == 0); } X static inline void ur(void) { X CHECK(atomic_read(&writers) == 0); X atomic_dec(&readers); X up_read(&rwsem_sem); } X static inline void sched(void) { #ifdef SCHED X schedule(); #endif } X int reader(void *arg) { X strcpy(current->comm, arg); X current->mm->arg_start = 0; X current->mm->arg_end = 0; X X atomic_inc(&runners); X X while (atomic_read(&do_stuff)) { X dr(); X ur(); X sched(); X } X X atomic_dec(&runners); X printk("%s: done\n",current->comm); X return 0; } X static void stop_test(unsigned long dummy) { X atomic_set(&do_stuff, 0); } X static int __init rwsem_init_module(void) { X printk(KERN_INFO "rwsem loading...\n"); X X init_rwsem(&rwsem_sem); X atomic_set(&do_stuff, 1); X #ifdef DEBUG_RWSEM X rwsem_to_monitor = &rwsem_sem; #endif X init_timer(&timer); X timer.function = stop_test; X timer.expires = jiffies + 5 * HZ; X add_timer(&timer); X X kernel_thread(reader, "ReadA", 0); X kernel_thread(reader, "ReadB", 0); X kernel_thread(reader, "ReadC", 0); X kernel_thread(reader, "ReadD", 0); X X return 0; } X static void __exit rwsem_cleanup_module(void) { X printk(KERN_INFO "rwsem unloading\n"); X X atomic_set(&do_stuff, 0); X del_timer(&timer); X while (atomic_read(&runners)) X schedule(); X printk("reads taken: %d\n", atomic_read(&reads_taken)); X printk("writes taken: %d\n", atomic_read(&writes_taken)); #ifdef DEBUG_RWSEM X rwsem_to_monitor = 0; #endif X remove_proc_entry("rwsem",NULL); X } X module_init(rwsem_init_module); module_exit(rwsem_cleanup_module); SHAR_EOF (set 20 01 04 19 21 37 17 'rwsem-ro.c'; eval "$shar_touch") && chmod 0644 'rwsem-ro.c' || $echo 'restore of' 'rwsem-ro.c' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'rwsem-ro.c:' 'MD5 check failed' ea56f13f27896585c247422a936d925b rwsem-ro.c SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'rwsem-ro.c'`" test 2499 -eq "$shar_count" || $echo 'rwsem-ro.c:' 'original size' '2499,' 'current size' "$shar_count!" fi fi # ============= rwsem-rw.c ============== if test -f 'rwsem-rw.c' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'rwsem-rw.c' '(file already exists)' else $echo 'x -' extracting 'rwsem-rw.c' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'rwsem-rw.c' && /* X * This is for the new, simple rwsems X */ X #define __NO_VERSION__ #include #include #include #include #include #include #include #include #include #include #include X struct rw_semaphore rwsem_sem; X #ifdef DEBUG_RWSEM extern struct rw_semaphore *rwsem_to_monitor; #endif X static atomic_t readers = ATOMIC_INIT(0); static atomic_t writers = ATOMIC_INIT(0); static atomic_t do_stuff = ATOMIC_INIT(0); static atomic_t runners = ATOMIC_INIT(0); static atomic_t reads_taken = ATOMIC_INIT(0); static atomic_t writes_taken = ATOMIC_INIT(0); X static struct timer_list timer; X #define CHECK(expr) \ X do { \ X if (!(expr)) { \ X printk("check " #expr " failed in " __FUNCTION__ "\n");\ X } \ X } while (0) X static inline void dr(void) { X down_read(&rwsem_sem); X atomic_inc(&readers); X atomic_inc(&reads_taken); X CHECK(atomic_read(&writers) == 0); } X static inline void ur(void) { X CHECK(atomic_read(&writers) == 0); X atomic_dec(&readers); X up_read(&rwsem_sem); } X static inline void dw(void) { X down_write(&rwsem_sem); X atomic_inc(&writers); X atomic_inc(&writes_taken); X CHECK(atomic_read(&writers) == 1); X CHECK(atomic_read(&readers) == 0); } X static inline void uw(void) { X CHECK(atomic_read(&writers) == 1); X CHECK(atomic_read(&readers) == 0); X atomic_dec(&writers); X up_write(&rwsem_sem); } X static inline void sched(void) { #ifdef SCHED X schedule(); #endif } X int reader(void *arg) { X strcpy(current->comm, arg); X current->mm->arg_start = 0; X current->mm->arg_end = 0; X X atomic_inc(&runners); X X while (atomic_read(&do_stuff)) { X dr(); X ur(); X sched(); X } X X atomic_dec(&runners); X printk("%s: done\n",current->comm); X return 0; } X int writer(void *arg) { X strcpy(current->comm, arg); X current->mm->arg_start = 0; X current->mm->arg_end = 0; X X atomic_inc(&runners); X X while (atomic_read(&do_stuff)) { X dw(); X uw(); X sched(); X } X X atomic_dec(&runners); X printk("%s: done\n",current->comm); X return 0; } X static void stop_test(unsigned long dummy) { X atomic_set(&do_stuff, 0); } X static int __init rwsem_init_module(void) { X printk(KERN_INFO "rwsem loading...\n"); X X init_rwsem(&rwsem_sem); X atomic_set(&do_stuff, 1); X #ifdef DEBUG_RWSEM X rwsem_to_monitor = &rwsem_sem; #endif X init_timer(&timer); X timer.function = stop_test; X timer.expires = jiffies + 5 * HZ; X add_timer(&timer); X X kernel_thread(writer, "WriteA", 0); X kernel_thread(writer, "WriteB", 0); X X kernel_thread(reader, "ReadA", 0); X kernel_thread(reader, "ReadB", 0); X kernel_thread(reader, "ReadC", 0); X kernel_thread(reader, "ReadD", 0); X X return 0; } X static void __exit rwsem_cleanup_module(void) { X printk(KERN_INFO "rwsem unloading\n"); X X atomic_set(&do_stuff, 0); X del_timer(&timer); X while (atomic_read(&runners)) X schedule(); X printk("reads taken: %d\n", atomic_read(&reads_taken)); X printk("writes taken: %d\n", atomic_read(&writes_taken)); #ifdef DEBUG_RWSEM X rwsem_to_monitor = 0; #endif X remove_proc_entry("rwsem",NULL); X } X module_init(rwsem_init_module); module_exit(rwsem_cleanup_module); SHAR_EOF (set 20 01 04 19 21 37 27 'rwsem-rw.c'; eval "$shar_touch") && chmod 0644 'rwsem-rw.c' || $echo 'restore of' 'rwsem-rw.c' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'rwsem-rw.c:' 'MD5 check failed' 0e0352bfded0418a41c1f54f2c7136a8 rwsem-rw.c SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'rwsem-rw.c'`" test 3179 -eq "$shar_count" || $echo 'rwsem-rw.c:' 'original size' '3179,' 'current size' "$shar_count!" fi fi # ============= rwsem-stat.txt ============== if test -f 'rwsem-stat.txt' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'rwsem-stat.txt' '(file already exists)' else $echo 'x -' extracting 'rwsem-stat.txt' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'rwsem-stat.txt' && TEST NUM READERS NUM WRITERS CONTENTION =============== =============== =============== ========== rwsem-rw 4 2 r-w & w-w rwsem-ro 4 0 no rwsem-wo 0 4 w-w only rwsem-r1 1 0 no rwsem-w1 0 1 no rwsem-r2 2 0 no X X ENVIRONMENT TEST SCHED READERS WRITERS =============================== ======= ======= =============== ======= Linux-2.4.4-pre3 + AA-rwsem rws-rw no 3330281 1009 X 3331972 994 X yes 1767102 607091 X 1743420 642095 X rws-ro no 2534630 n/a X 3535202 n/a X yes 2837218 n/a X 3164814 n/a X rws-wo no n/a 2507449 X n/a 2399102 X yes n/a 1568467 X n/a 1412262 X rws-r1 no 9232485 n/a X 9217585 n/a X yes 5483757 n/a X 5487028 n/a X rws-w1 no n/a 9900333 X n/a 9918021 X yes n/a 5745657 X n/a 5747063 X rws-r2 no 3499275 n/a X 3518590 n/a X yes 3184431 n/a X 3180287 n/a X ------------------------------- ------- ------- --------------- ------- Linux-2.4.4-pre4 [XADD] rws-rw no 563388 283005 X 558159 280288 X yes 683670 197017 X 700714 194316 X rws-ro no 6316985 n/a X 6314241 n/a X yes 4309406 n/a X 4575043 n/a X rws-wo no n/a 765699 X n/a 763876 X yes n/a 650512 X n/a 652287 X rws-r1 no 15171532 n/a X 15158899 n/a X yes 7222310 n/a X 7229793 n/a X rws-w1 no n/a 13942744 X n/a 13991823 X yes n/a 7362605 X n/a 7356127 X rws-r2 no 5517671 n/a X 5516168 n/a X yes 3452796 n/a X 3331947 n/a X ------------------------------- ------- ------- --------------- ------- Linux-2.4.4-pre4 [XADD] rws-rw no 531929 267129 X + slightly-unfair-contention 531093 266822 X tweak yes 839560 185670 X 903995 183958 X rws-ro no 6318293 n/a X 6320336 n/a X yes 4257862 n/a X 4315243 n/a X rws-wo no n/a 766427 X n/a 766471 X yes n/a 644036 X n/a 642236 X X ------------------------------- ------- ------- --------------- ------- Linux-2.4.4-pre4 [GENERIC-SPIN] rws-rw no 545138 274002 X 545378 273785 X yes 755343 187874 X 745888 185562 X rws-ro no 4500398 n/a X 4506583 n/a X yes 3137883 n/a X 3129119 n/a X rws-wo no n/a 763599 X n/a 763059 X yes n/a 641256 X n/a 647319 X rws-r1 no 13110083 n/a X 13115436 n/a X yes 6950687 n/a X 6951901 n/a X rws-w1 no n/a 13004627 X n/a 13003754 X yes n/a 6899764 X n/a 6898953 X rws-r2 no 4741615 n/a X 4746860 n/a X yes 3340292 n/a X 2967268 n/a SHAR_EOF (set 20 01 04 19 23 22 19 'rwsem-stat.txt'; eval "$shar_touch") && chmod 0644 'rwsem-stat.txt' || $echo 'restore of' 'rwsem-stat.txt' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'rwsem-stat.txt:' 'MD5 check failed' 3cb1536ef80b52ce59ac03a320e4d4c1 rwsem-stat.txt SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'rwsem-stat.txt'`" test 2619 -eq "$shar_count" || $echo 'rwsem-stat.txt:' 'original size' '2619,' 'current size' "$shar_count!" fi fi # ============= rwsem-w1.c ============== if test -f 'rwsem-w1.c' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'rwsem-w1.c' '(file already exists)' else $echo 'x -' extracting 'rwsem-w1.c' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'rwsem-w1.c' && /* X * This is for the new, simple rwsems X */ X #define __NO_VERSION__ #include #include #include #include #include #include #include #include #include #include #include X struct rw_semaphore rwsem_sem; X #ifdef DEBUG_RWSEM extern struct rw_semaphore *rwsem_to_monitor; #endif X static atomic_t readers = ATOMIC_INIT(0); static atomic_t writers = ATOMIC_INIT(0); static atomic_t do_stuff = ATOMIC_INIT(0); static atomic_t runners = ATOMIC_INIT(0); static atomic_t reads_taken = ATOMIC_INIT(0); static atomic_t writes_taken = ATOMIC_INIT(0); X static struct timer_list timer; X #define CHECK(expr) \ X do { \ X if (!(expr)) { \ X printk("check " #expr " failed in " __FUNCTION__ "\n");\ X } \ X } while (0) X static inline void dw(void) { X down_write(&rwsem_sem); X atomic_inc(&writers); X atomic_inc(&writes_taken); X CHECK(atomic_read(&writers) == 1); X CHECK(atomic_read(&readers) == 0); } X static inline void uw(void) { X CHECK(atomic_read(&writers) == 1); X CHECK(atomic_read(&readers) == 0); X atomic_dec(&writers); X up_write(&rwsem_sem); } X static inline void sched(void) { #ifdef SCHED X schedule(); #endif } X int writer(void *arg) { X strcpy(current->comm, arg); X current->mm->arg_start = 0; X current->mm->arg_end = 0; X X atomic_inc(&runners); X X while (atomic_read(&do_stuff)) { X dw(); X uw(); X sched(); X } X X atomic_dec(&runners); X printk("%s: done\n",current->comm); X return 0; } X static void stop_test(unsigned long dummy) { X atomic_set(&do_stuff, 0); } X static int __init rwsem_init_module(void) { X printk(KERN_INFO "rwsem loading...\n"); X X init_rwsem(&rwsem_sem); X atomic_set(&do_stuff, 1); X #ifdef DEBUG_RWSEM X rwsem_to_monitor = &rwsem_sem; #endif X init_timer(&timer); X timer.function = stop_test; X timer.expires = jiffies + 5 * HZ; X add_timer(&timer); X X kernel_thread(writer, "WriteA", 0); X X return 0; } X static void __exit rwsem_cleanup_module(void) { X printk(KERN_INFO "rwsem unloading\n"); X X atomic_set(&do_stuff, 0); X del_timer(&timer); X while (atomic_read(&runners)) X schedule(); X printk("reads taken: %d\n", atomic_read(&reads_taken)); X printk("writes taken: %d\n", atomic_read(&writes_taken)); #ifdef DEBUG_RWSEM X rwsem_to_monitor = 0; #endif X remove_proc_entry("rwsem",NULL); X } X module_init(rwsem_init_module); module_exit(rwsem_cleanup_module); SHAR_EOF (set 20 01 04 19 21 37 39 'rwsem-w1.c'; eval "$shar_touch") && chmod 0644 'rwsem-w1.c' || $echo 'restore of' 'rwsem-w1.c' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'rwsem-w1.c:' 'MD5 check failed' a3c20d6d0af402a7592b7645c3f666a4 rwsem-w1.c SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'rwsem-w1.c'`" test 2467 -eq "$shar_count" || $echo 'rwsem-w1.c:' 'original size' '2467,' 'current size' "$shar_count!" fi fi # ============= rwsem-wo.c ============== if test -f 'rwsem-wo.c' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'rwsem-wo.c' '(file already exists)' else $echo 'x -' extracting 'rwsem-wo.c' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'rwsem-wo.c' && /* X * This is for the new, simple rwsems X */ X #define __NO_VERSION__ #include #include #include #include #include #include #include #include #include #include #include X struct rw_semaphore rwsem_sem; X #ifdef DEBUG_RWSEM extern struct rw_semaphore *rwsem_to_monitor; #endif X static atomic_t readers = ATOMIC_INIT(0); static atomic_t writers = ATOMIC_INIT(0); static atomic_t do_stuff = ATOMIC_INIT(0); static atomic_t runners = ATOMIC_INIT(0); static atomic_t reads_taken = ATOMIC_INIT(0); static atomic_t writes_taken = ATOMIC_INIT(0); X static struct timer_list timer; X #define CHECK(expr) \ X do { \ X if (!(expr)) { \ X printk("check " #expr " failed in " __FUNCTION__ "\n");\ X } \ X } while (0) X static inline void dw(void) { X down_write(&rwsem_sem); X atomic_inc(&writers); X atomic_inc(&writes_taken); X CHECK(atomic_read(&writers) == 1); X CHECK(atomic_read(&readers) == 0); } X static inline void uw(void) { X CHECK(atomic_read(&writers) == 1); X CHECK(atomic_read(&readers) == 0); X atomic_dec(&writers); X up_write(&rwsem_sem); } X static inline void sched(void) { #ifdef SCHED X schedule(); #endif } X int writer(void *arg) { X strcpy(current->comm, arg); X current->mm->arg_start = 0; X current->mm->arg_end = 0; X X atomic_inc(&runners); X X while (atomic_read(&do_stuff)) { X dw(); X uw(); X sched(); X } X X atomic_dec(&runners); X printk("%s: done\n",current->comm); X return 0; } X static void stop_test(unsigned long dummy) { X atomic_set(&do_stuff, 0); } X static int __init rwsem_init_module(void) { X printk(KERN_INFO "rwsem loading...\n"); X X init_rwsem(&rwsem_sem); X atomic_set(&do_stuff, 1); X #ifdef DEBUG_RWSEM X rwsem_to_monitor = &rwsem_sem; #endif X init_timer(&timer); X timer.function = stop_test; X timer.expires = jiffies + 5 * HZ; X add_timer(&timer); X X kernel_thread(writer, "WriteA", 0); X kernel_thread(writer, "WriteB", 0); X kernel_thread(writer, "WriteC", 0); X kernel_thread(writer, "WriteD", 0); X X return 0; } X static void __exit rwsem_cleanup_module(void) { X printk(KERN_INFO "rwsem unloading\n"); X X atomic_set(&do_stuff, 0); X del_timer(&timer); X while (atomic_read(&runners)) X schedule(); X printk("reads taken: %d\n", atomic_read(&reads_taken)); X printk("writes taken: %d\n", atomic_read(&writes_taken)); #ifdef DEBUG_RWSEM X rwsem_to_monitor = 0; #endif X remove_proc_entry("rwsem",NULL); X } X module_init(rwsem_init_module); module_exit(rwsem_cleanup_module); SHAR_EOF (set 20 01 04 19 21 37 44 'rwsem-wo.c'; eval "$shar_touch") && chmod 0644 'rwsem-wo.c' || $echo 'restore of' 'rwsem-wo.c' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'rwsem-wo.c:' 'MD5 check failed' d2a6d6a11e9ed7dafcb6d593b5872705 rwsem-wo.c SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'rwsem-wo.c'`" test 2578 -eq "$shar_count" || $echo 'rwsem-wo.c:' 'original size' '2578,' 'current size' "$shar_count!" fi fi # ============= wibble.c ============== if test -f 'wibble.c' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'wibble.c' '(file already exists)' else $echo 'x -' extracting 'wibble.c' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'wibble.c' && /* X * This is for the new, simple rwsems X */ X #include #include X #if 0 void dr(struct rw_semaphore *sem) { X down_read(sem); } #endif X void ur(struct rw_semaphore *sem) { X up_read(sem); } X #if 0 void dw(struct rw_semaphore *sem) { X down_write(sem); } X void uw(struct rw_semaphore *sem) { X up_write(sem); } #endif SHAR_EOF (set 20 01 04 20 13 03 44 'wibble.c'; eval "$shar_touch") && chmod 0644 'wibble.c' || $echo 'restore of' 'wibble.c' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'wibble.c:' 'MD5 check failed' fb5d951f81e8e0aa90bbea320c410e02 wibble.c SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'wibble.c'`" test 345 -eq "$shar_count" || $echo 'wibble.c:' 'original size' '345,' 'current size' "$shar_count!" fi fi rm -fr _sh00477 exit 0 - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/