many readers and some writers: how to queue them to avoid da

I’m reading ftp://ftp.qnx.com/usr/free/qnx4/os/libs/sync.tgz.readme as I
plan to use ftp://ftp.qnx.com/usr/free/qnx4/os/libs/sync.tgz to arbitrate
read and write access to the set of files.

There will be several processes reading files and one~two processes
writing to the same files.

Please give a hint - how do they know the names of the locks?
Do I initialize something prior to starting those processes and by that I
create lock’s names to use in readers and writers?

Tony.

This is what I see in rwlock.c:

int
init_rwlock(rwlock_t *p)
{
INITLOCK(p);
sem_init(&p->readwait, 0, 0);
sem_init(&p->writewait, 0, 0);
p->nreaders = p->nwriters = 0;
p->waitinreaders = p->waitinwriters = 0;
return 0;
}

The sem_init()'s second parameter is “int pshared”, if it is non-zero -
the semaphore is shared between the processes in the shared memory.
What if “int pshared” is zero as in the above “init_rwlock()” definition?
Does this mean I can not share theese semaphores in the shared memory?

May I edit the “init_rwlock()” definition so that “sem_init(&p->readwait,
1, 0); sem_init(&p->writewait, 1, 0);”, will it allow me to share the
semaphore structure?

I plan (now) to have the initializing prosess that will create the shared
memory and the semaphores there. This process is supposed to live forever.
All readers and writers would search the shared memory for the
semaphores…

Will it work for me?

Tony.

What frightens me is:

int
read_lock(volatile rwlock_t *l)
{
LOCK(l);
if (l->nwriters || l->waitingreaders || l->waitingwriters){
UNLOCK(l);
sem_wait(&l->readwait);
return 0;
}
l->nreaders++;
UNLOCK(l);
return 0;
}

If I were the first and only reader trying to read_lock() while there are
writers in progress, I will never increment “nreaders”.
The first thing I do after I read what I wanted (when I get my turn) - is
“read_unlock()”.

int
read_unlock(volatile rwlock_t *rw)
{
LOCK(rw);
rw->nreaders–;
if (rw->waitingwriters && rw->nreaders == 0) {
rw->nwriters = 1;
rw->waitingwriters–;
UNLOCK(rw);
sem_post(&rw->writewait);
return 0;
}
UNLOCK(rw);
return 0;
}

And what scaring me is: I’ll immediatelly decrement the variable that I
did not increment previously (“nreaders”)!

Please comment…

Tony.

It’s getting scarier…

I got hold of yet another version of sync.tar.gz.
The unified diff between the two packages is:

diff -ru v1/rwlock.c v2/rwlock.c
— v1/rwlock.c 1997-07-30 21:41:14.000000000 +0400
+++ v2/rwlock.c 1997-07-30 21:42:27.000000000 +0400
@@ -17,7 +17,7 @@
read_lock(volatile rwlock_t *l)
{
LOCK(l);

  • if (l->nwriters || l->waitingreaders || l->waitingwriters) {
  • if (l->nwriters) {
    l->waitingreaders++;
    UNLOCK(l);
    sem_wait(&l->readwait);

The code simplification was devised in less than two minutes…
However, the “decrementation of the previously non-incremented variable”
remains in place.

I’m drawing a flow-chart in attempt to understand all this matter.

May be I’m on the completely wrong path with using theese semaphores. They
were devised (I’m told) for threading in QNX4, which I do not use.
I need to arbitrate access to the Fsys objects - the real files on the
filesystem. The readers and writers are different processes, not the
threads of one process.

What other means of queueing the file IO is available in QNX4?

Tony.

PS
I did manage to get it work with sync.tar.gz v1(1997-07-30
21:41:14.000000000 +0400), three readers and two writers behave as
expected seems so far.

Tony wrote:

May be I’m on the completely wrong path with using theese semaphores.
They were devised (I’m told) for threading in QNX4, which I do not use.
I need to arbitrate access to the Fsys objects - the real files on the
filesystem. The readers and writers are different processes, not the
threads of one process.
What other means of queueing the file IO is available in QNX4?

Fsys supports the advisory locking model; refer fcntl() and F_SETLK and
F_SETLKW. F_RDLCK are reader locks (many readers) and F_WRLCK are
writers (single). Note the way advisory locks work is that it is up
to the application to first obtain the appropriate lock on the relevant
region of the file (using fcntl, which will error or block as needed),
then do the read() or write() call (Fsys will not error these if there
is a locking conflict), and then F_UNLCK to release the locked range.
This is all documented in the QNX4/WatcomC Library Reference book …