voron

experimental ARM OS
git clone git://git.2f30.org/voron.git
Log | Files | Refs | LICENSE

commit dfc4ad349414b5c840eb245f66b09a436887ef97
parent 3ec1004731beb8400a4bf07417e8b6d5e5294e36
Author: oblique <psyberbits@gmail.com>
Date:   Wed Apr  3 11:56:59 +0300

move readers-writer lock to rwlock.h

Diffstat:
include/rwlock.h | 154+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/semaphore.h | 148-------------------------------------------------------------------------------
2 files changed, 154 insertions(+), 148 deletions(-)
diff --git a/include/rwlock.h b/include/rwlock.h @@ -0,0 +1,154 @@ +#ifndef __RWLOCK_H +#define __RWLOCK_H + +#include <inttypes.h> +#include <semaphore.h> + +/* readers-writer lock + * implemented with 'Passing the Baton' technique + * + * rules: + * 1) if we have an awakened writer or writers in the queue then + * a new reader will be added in readers' queue. + * 2) if all awakened readers are done then we awake a writer, + * even if we have readers in the queue. + * 3) if the awakened writer and all writers in the queue are done + * then we awake all the readers. */ +typedef struct { + mutex_t lock; + mutex_t writer_wait; + mutex_t reader_wait; + u32 nr_writers; + u32 nr_readers; + u32 nr_writers_queue; + u32 nr_readers_queue; +} rwlock_t; + +#define RWLOCK_INIT { \ + MUTEX_INIT, \ + MUTEX_INIT_LOCKED, \ + MUTEX_INIT_LOCKED, \ + 0, \ + 0, \ + 0, \ + 0 \ +} + +static inline void +rwlock_init(rwlock_t *rwl) +{ + mutex_init(&rwl->lock); + mutex_init(&rwl->writer_wait); + mutex_lock(&rwl->writer_wait); + mutex_init(&rwl->reader_wait); + mutex_lock(&rwl->reader_wait); + rwl->nr_writers = 0; + rwl->nr_readers = 0; + rwl->nr_writers_queue = 0; + rwl->nr_readers_queue = 0; +} + +static inline void +rwlock_rdlock(rwlock_t *rwl) +{ + mutex_lock(&rwl->lock); + /* if we have awakened writer or writers in the queue then wait */ + if (rwl->nr_writers > 0 || rwl->nr_writers_queue > 0) { + rwl->nr_readers_queue++; + mutex_unlock(&rwl->lock); + /* wait */ + mutex_lock(&rwl->reader_wait); + } + + rwl->nr_readers++; + + /* if there is at least one reader in the queue, + * awake it (i.e. awake the next reader) */ + if (rwl->nr_readers_queue > 0) { + rwl->nr_readers_queue--; + mutex_unlock(&rwl->reader_wait); + } else { + mutex_unlock(&rwl->lock); + } +} + +/* returns 1 if managed to lock + * returns 0 if not */ +static inline int +rwlock_tryrdlock(rwlock_t *rwl) +{ + mutex_lock(&rwl->lock); + /* if we have awakened writer or writers in the queue then we can't lock */ + if (rwl->nr_writers > 0 || rwl->nr_writers_queue > 0) { + mutex_unlock(&rwl->lock); + return 0; + } + + rwl->nr_readers++; + mutex_unlock(&rwl->lock); + return 1; +} + +static inline void +rwlock_wrlock(rwlock_t *rwl) +{ + mutex_lock(&rwl->lock); + /* if we have an awakened writer or awakened readers then wait */ + if (rwl->nr_writers > 0 || rwl->nr_readers > 0) { + rwl->nr_writers_queue++; + mutex_unlock(&rwl->lock); + /* wait */ + mutex_lock(&rwl->writer_wait); + } + + rwl->nr_writers++; + mutex_unlock(&rwl->lock); +} + +/* returns 1 if managed to lock + * returns 0 if not */ +static inline int +rwlock_trywrlock(rwlock_t *rwl) +{ + mutex_lock(&rwl->lock); + /* if we have an awakened writer or awakened readers then we can't lock */ + if (rwl->nr_writers > 0 || rwl->nr_readers > 0) { + mutex_unlock(&rwl->lock); + return 0; + } + + rwl->nr_writers++; + mutex_unlock(&rwl->lock); + return 1; +} + +static inline void +rwlock_unlock(rwlock_t *rwl) +{ + mutex_lock(&rwl->lock); + + /* a reader is done */ + if (rwl->nr_readers > 0) { + rwl->nr_readers--; + /* a writer is done */ + } else if (rwl->nr_writers > 0) { + rwl->nr_writers--; + } + + /* if all awakened readers are done and we have writers in the queue + * then awake a writer */ + if (rwl->nr_readers == 0 && rwl->nr_writers_queue > 0) { + rwl->nr_writers_queue--; + mutex_unlock(&rwl->writer_wait); + /* if the awakened writer and all writers from the queue are done + * then awake a reader */ + } else if (rwl->nr_writers == 0 && rwl->nr_writers_queue == 0 && + rwl->nr_readers_queue > 0) { + rwl->nr_readers_queue--; + mutex_unlock(&rwl->reader_wait); + } else { + mutex_unlock(&rwl->lock); + } +} + +#endif /* __RWLOCK_H */ diff --git a/include/semaphore.h b/include/semaphore.h @@ -109,152 +109,4 @@ mutex_unlock(mutex_t *mut) semaphore_done(&mut->sem); } - -/* readers-writer lock - * implemented with 'Passing the Baton' technique - * - * rules: - * 1) if we have an awakened writer or writers in the queue then - * a new reader will be added in readers' queue. - * 2) if all awakened readers are done then we awake a writer, - * even if we have readers in the queue. - * 3) if the awakened writer and all writers in the queue are done - * then we awake all the readers. */ -typedef struct { - mutex_t lock; - mutex_t writer_wait; - mutex_t reader_wait; - u32 nr_writers; - u32 nr_readers; - u32 nr_writers_queue; - u32 nr_readers_queue; -} rwlock_t; - -#define RWLOCK_INIT { \ - MUTEX_INIT, \ - MUTEX_INIT_LOCKED, \ - MUTEX_INIT_LOCKED, \ - 0, \ - 0, \ - 0, \ - 0 \ -} - -static inline void -rwlock_init(rwlock_t *rwl) -{ - mutex_init(&rwl->lock); - mutex_init(&rwl->writer_wait); - mutex_lock(&rwl->writer_wait); - mutex_init(&rwl->reader_wait); - mutex_lock(&rwl->reader_wait); - rwl->nr_writers = 0; - rwl->nr_readers = 0; - rwl->nr_writers_queue = 0; - rwl->nr_readers_queue = 0; -} - -static inline void -rwlock_rdlock(rwlock_t *rwl) -{ - mutex_lock(&rwl->lock); - /* if we have awakened writer or writers in the queue then wait */ - if (rwl->nr_writers > 0 || rwl->nr_writers_queue > 0) { - rwl->nr_readers_queue++; - mutex_unlock(&rwl->lock); - /* wait */ - mutex_lock(&rwl->reader_wait); - } - - rwl->nr_readers++; - - /* if there is at least one reader in the queue, - * awake it (i.e. awake the next reader) */ - if (rwl->nr_readers_queue > 0) { - rwl->nr_readers_queue--; - mutex_unlock(&rwl->reader_wait); - } else { - mutex_unlock(&rwl->lock); - } -} - -/* returns 1 if managed to lock - * returns 0 if not */ -static inline int -rwlock_tryrdlock(rwlock_t *rwl) -{ - mutex_lock(&rwl->lock); - /* if we have awakened writer or writers in the queue then we can't lock */ - if (rwl->nr_writers > 0 || rwl->nr_writers_queue > 0) { - mutex_unlock(&rwl->lock); - return 0; - } - - rwl->nr_readers++; - mutex_unlock(&rwl->lock); - return 1; -} - -static inline void -rwlock_wrlock(rwlock_t *rwl) -{ - mutex_lock(&rwl->lock); - /* if we have an awakened writer or awakened readers then wait */ - if (rwl->nr_writers > 0 || rwl->nr_readers > 0) { - rwl->nr_writers_queue++; - mutex_unlock(&rwl->lock); - /* wait */ - mutex_lock(&rwl->writer_wait); - } - - rwl->nr_writers++; - mutex_unlock(&rwl->lock); -} - -/* returns 1 if managed to lock - * returns 0 if not */ -static inline int -rwlock_trywrlock(rwlock_t *rwl) -{ - mutex_lock(&rwl->lock); - /* if we have an awakened writer or awakened readers then we can't lock */ - if (rwl->nr_writers > 0 || rwl->nr_readers > 0) { - mutex_unlock(&rwl->lock); - return 0; - } - - rwl->nr_writers++; - mutex_unlock(&rwl->lock); - return 1; -} - -static inline void -rwlock_unlock(rwlock_t *rwl) -{ - mutex_lock(&rwl->lock); - - /* a reader is done */ - if (rwl->nr_readers > 0) { - rwl->nr_readers--; - /* a writer is done */ - } else if (rwl->nr_writers > 0) { - rwl->nr_writers--; - } - - /* if all awakened readers are done and we have writers in the queue - * then awake a writer */ - if (rwl->nr_readers == 0 && rwl->nr_writers_queue > 0) { - rwl->nr_writers_queue--; - mutex_unlock(&rwl->writer_wait); - /* if the awakened writer and all writers from the queue are done - * then awake a reader */ - } else if (rwl->nr_writers == 0 && rwl->nr_writers_queue == 0 && - rwl->nr_readers_queue > 0) { - rwl->nr_readers_queue--; - mutex_unlock(&rwl->reader_wait); - } else { - mutex_unlock(&rwl->lock); - } -} - #endif /* __SEMAPHORE_H */