Author: Remi Meier <remi.me...@gmail.com> Branch: c7 Changeset: r639:cf5b0f66205f Date: 2014-01-18 13:44 +0100 http://bitbucket.org/pypy/stmgc/changeset/cf5b0f66205f/
Log: add files... diff --git a/c7/reader_writer_lock.c b/c7/reader_writer_lock.c new file mode 100644 --- /dev/null +++ b/c7/reader_writer_lock.c @@ -0,0 +1,93 @@ +/* Taken from: http://locklessinc.com/articles/locks/ + + Sticking to semi-portable C code, we can still do a little better. + There exists a form of the ticket lock that is designed for read-write + locks. An example written in assembly was posted to the Linux kernel + mailing list in 2002 by David Howells from RedHat. This was a highly + optimized version of a read-write ticket lock developed at IBM in the + early 90's by Joseph Seigh. Note that a similar (but not identical) + algorithm was published by John Mellor-Crummey and Michael Scott in + their landmark paper "Scalable Reader-Writer Synchronization for + Shared-Memory Multiprocessors". Converting the algorithm from + assembly language to C yields: +*/ + +#include "reader_writer_lock.h" + + +#define EBUSY 1 +#define atomic_xadd(P, V) __sync_fetch_and_add((P), (V)) +#define cmpxchg(P, O, N) __sync_val_compare_and_swap((P), (O), (N)) +#define atomic_inc(P) __sync_add_and_fetch((P), 1) +#define atomic_dec(P) __sync_add_and_fetch((P), -1) +#define atomic_add(P, V) __sync_add_and_fetch((P), (V)) +#define atomic_set_bit(P, V) __sync_or_and_fetch((P), 1<<(V)) +#define atomic_clear_bit(P, V) __sync_and_and_fetch((P), ~(1<<(V))) +/* Compile read-write barrier */ +#define barrier() asm volatile("": : :"memory") + +/* Pause instruction to prevent excess processor bus usage */ +#define cpu_relax() asm volatile("pause\n": : :"memory") + + + +void rwticket_wrlock(rwticket *l) +{ + unsigned me = atomic_xadd(&l->u, (1<<16)); + unsigned char val = me >> 16; + + while (val != l->s.write) cpu_relax(); +} + +int rwticket_wrunlock(rwticket *l) +{ + rwticket t = *l; + + barrier(); + + t.s.write++; + t.s.read++; + + *(unsigned short *) l = t.us; + return 0; +} + +int rwticket_wrtrylock(rwticket *l) +{ + unsigned me = l->s.users; + unsigned char menew = me + 1; + unsigned read = l->s.read << 8; + unsigned cmp = (me << 16) + read + me; + unsigned cmpnew = (menew << 16) + read + me; + + if (cmpxchg(&l->u, cmp, cmpnew) == cmp) return 0; + + return EBUSY; +} + +void rwticket_rdlock(rwticket *l) +{ + unsigned me = atomic_xadd(&l->u, (1<<16)); + unsigned char val = me >> 16; + + while (val != l->s.read) cpu_relax(); + l->s.read++; +} + +void rwticket_rdunlock(rwticket *l) +{ + atomic_inc(&l->s.write); +} + +int rwticket_rdtrylock(rwticket *l) +{ + unsigned me = l->s.users; + unsigned write = l->s.write; + unsigned char menew = me + 1; + unsigned cmp = (me << 16) + (me << 8) + write; + unsigned cmpnew = ((unsigned) menew << 16) + (menew << 8) + write; + + if (cmpxchg(&l->u, cmp, cmpnew) == cmp) return 0; + + return EBUSY; +} diff --git a/c7/reader_writer_lock.h b/c7/reader_writer_lock.h new file mode 100644 --- /dev/null +++ b/c7/reader_writer_lock.h @@ -0,0 +1,22 @@ + +typedef union rwticket rwticket; +union rwticket +{ + unsigned u; + unsigned short us; + struct + { + unsigned char write; + unsigned char read; + unsigned char users; + } s; +}; + +void rwticket_wrlock(rwticket *l); +int rwticket_wrunlock(rwticket *l); +int rwticket_wrtrylock(rwticket *l); +void rwticket_rdlock(rwticket *l); +void rwticket_rdunlock(rwticket *l); +int rwticket_rdtrylock(rwticket *l); + + _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit