I'm looking for the rwsem-rw benchmark that Andrea Arcangeli and David Howells were used around April 2001 when they discussed the rw-semaphore optimization. I searched LKML, but didn't see the benchmark code. Appreciate if someone can dig it up and pass them along. Thanks.
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 <[email protected]>.
# 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 ([email protected]).
X */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
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 ([email protected]).
X */
X
#define __NO_VERSION__
#include <linux/config.h>
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/personality.h>
#include <linux/smp_lock.h>
#include <linux/delay.h>
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 <linux/config.h>
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <asm/atomic.h>
#include <linux/personality.h>
#include <linux/smp_lock.h>
#include <linux/delay.h>
#include <linux/timer.h>
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 <linux/config.h>
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <asm/atomic.h>
#include <linux/personality.h>
#include <linux/smp_lock.h>
#include <linux/delay.h>
#include <linux/timer.h>
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 <linux/config.h>
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <asm/atomic.h>
#include <linux/personality.h>
#include <linux/smp_lock.h>
#include <linux/delay.h>
#include <linux/timer.h>
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 <linux/config.h>
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <asm/atomic.h>
#include <linux/personality.h>
#include <linux/smp_lock.h>
#include <linux/delay.h>
#include <linux/timer.h>
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 <linux/config.h>
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <asm/atomic.h>
#include <linux/personality.h>
#include <linux/smp_lock.h>
#include <linux/delay.h>
#include <linux/timer.h>
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 <linux/config.h>
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <asm/atomic.h>
#include <linux/personality.h>
#include <linux/smp_lock.h>
#include <linux/delay.h>
#include <linux/timer.h>
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 <linux/config.h>
#include <linux/rwsem.h>
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