Hello,

currently it is possible to write-starve the read-write lock.
It is also the default behavior in glibc and musl libc pthreads.

I am dealing with a situation in my project which would "benefit"
from writer prioritized rwlocks, but I hacked around this with a
"halting" mutex that stops the readers from entering the critical
section. (in my use case, the rwlocks are very often writer-starved)

Just curious if you would be interested in this, or against such
modification. Below is a diff that trivially fixes the starvation.

If people are not against, I would like to open a PR with this,
or possibly something more sophisticated in the future.


Thanks, take care.

--
mc


diff --git a/uspace/lib/c/include/fibril_synch.h 
b/uspace/lib/c/include/fibril_synch.h
index fc32aa13d..905f484e1 100644
--- a/uspace/lib/c/include/fibril_synch.h
+++ b/uspace/lib/c/include/fibril_synch.h
@@ -99,6 +99,7 @@ typedef struct {
        fibril_owner_info_t oi;  /**< Keep this the first thing. */
        unsigned int writers;
        unsigned int readers;
+       unsigned int writers_in_queue;
        list_t waiters;
 } fibril_rwlock_t;
 
diff --git a/uspace/lib/c/generic/thread/fibril_synch.c 
b/uspace/lib/c/generic/thread/fibril_synch.c
index 2326d001a..fcb01c97c 100644
--- a/uspace/lib/c/generic/thread/fibril_synch.c
+++ b/uspace/lib/c/generic/thread/fibril_synch.c
@@ -236,6 +236,7 @@ void fibril_rwlock_initialize(fibril_rwlock_t *frw)
        frw->oi.owned_by = NULL;
        frw->writers = 0;
        frw->readers = 0;
+       frw->writers_in_queue = 0;
        list_initialize(&frw->waiters);
 }
 
@@ -245,7 +246,7 @@ void fibril_rwlock_read_lock(fibril_rwlock_t *frw)
 
        futex_lock(&fibril_synch_futex);
 
-       if (!frw->writers) {
+       if (!frw->writers && frw->writers_in_queue == 0) {
                /* Consider the first reader the owner. */
                if (frw->readers++ == 0)
                        frw->oi.owned_by = f;
@@ -282,6 +283,7 @@ void fibril_rwlock_write_lock(fibril_rwlock_t *frw)
 
        awaiter_t wdata = AWAITER_INIT;
        list_append(&wdata.link, &frw->waiters);
+       frw->writers_in_queue++;
        check_for_deadlock(&frw->oi);
        f->waits_for = &frw->oi;
 
@@ -331,6 +333,7 @@ static void _fibril_rwlock_common_unlock(fibril_rwlock_t 
*frw)
                        if (frw->readers)
                                break;
                        frw->writers++;
+                       frw->writers_in_queue--;
                } else {
                        frw->readers++;
                }


_______________________________________________
HelenOS-devel mailing list
[email protected]
http://lists.modry.cz/listinfo/helenos-devel

Reply via email to