From: <ljs...@us...> - 2008-05-20 03:05:51
|
Revision: 588 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=588&view=rev Author: ljsebald Date: 2008-05-19 20:05:38 -0700 (Mon, 19 May 2008) Log Message: ----------- Add support for "upgrading" a reader/writer semaphore from a read lock to a write lock. Modified Paths: -------------- kos/include/kos/rwsem.h kos/kernel/thread/rwsem.c Modified: kos/include/kos/rwsem.h =================================================================== --- kos/include/kos/rwsem.h 2008-05-20 02:45:34 UTC (rev 587) +++ kos/include/kos/rwsem.h 2008-05-20 03:05:38 UTC (rev 588) @@ -71,6 +71,17 @@ EWOULDBLOCK - would block */ int rwsem_write_trylock(rw_semaphore_t *s); +/* "Upgrade" a read lock to a write lock. Returns -1 on error. + EPERM - called inside an interrupt + EINTR - was interrupted */ +int rwsem_read_upgrade(rw_semaphore_t *s); + +/* Attempt to upgrade a read lock to a write lock. If the call to + rwsem_read_upgrade() would normally block, return -1 for error. + Note that on error, the read lock is still held. + EWOULDBLOCK - would block */ +int rwsem_read_tryupgrade(rw_semaphore_t *s); + /* Return the reader/writer semaphore reader count */ int rwsem_read_count(rw_semaphore_t *s); Modified: kos/kernel/thread/rwsem.c =================================================================== --- kos/kernel/thread/rwsem.c 2008-05-20 02:45:34 UTC (rev 587) +++ kos/kernel/thread/rwsem.c 2008-05-20 03:05:38 UTC (rev 588) @@ -201,6 +201,60 @@ return rv; } +/* "Upgrade" a read lock to a write lock. */ +int rwsem_read_upgrade(rw_semaphore_t *s) { + int old, rv = 0; + + if(irq_inside_int()) { + dbglog(DBG_WARNING, "rwsem_read_upgrade: called inside interrupt\n"); + errno = EPERM; + return -1; + } + + old = irq_disable(); + + --s->read_count; + + /* If there are still other readers, wait patiently for our turn. */ + if(s->read_count) { + rv = genwait_wait(&s->write_lock, "rwsem_read_upgrade", 0, NULL); + + if(rv < 0) { + assert(errno == EINTR); + rv = -1; + } + else { + s->write_lock = 1; + } + } + else { + s->write_lock = 1; + } + + irq_restore(old); + return rv; +} + +/* Attempt to upgrade a read lock to a write lock, but do not block. */ +int rwsem_read_tryupgrade(rw_semaphore_t *s) { + int old, rv; + + old = irq_disable(); + + if(s->read_count != 1) { + rv = -1; + errno = EWOULDBLOCK; + } + else { + rv = 0; + s->read_count = 0; + s->write_lock = 1; + } + + irq_restore(old); + return rv; +} + /* Return the current reader count */ int rwsem_read_count(rw_semaphore_t *s) { return s->read_count; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |