qlock(2) doesn't block all threads in a proc.  i'm terrible
at explaining code, but here it goes....

from the source, you'll see that the thread library sets
up (/sys/src/libthread/main.c:35)

        _qlockinit(_threadrendezvous);

what does this do?  in /sys/src/libc/9sys/qlock.c we see
that this just sets a function pointer used in qlock.

qlock returns if unlocked otherwise calls the function
ptr set by _qlockinit() until it returns a magic value.

back in the thread library (/sys/src/libthread/rendez.c)
we find _threadrendezvous.  _threadrendezvous has
two cases.  there is a matching tag (somebody's waiting
to rendezvous with us), and there isn't.  the first case
is qunlock.  the second is qlock when the lock is locked.

in that case, we set set up for going to sleep and then
let _sched give the processor to another thread.

here's some code that shows how this works:

#include<u.h>
#include<libc.h>
#include<thread.h>

QLock q;

void
lockthread(void*)
{
        qlock(&q);
        for(;;){
                print("lockthread\n");
                sleep(100);
                yield();
        }
        qunlock(&q);
}

void
noisethread(void*)
{
        for(;;){
                print("hi mom\n");
                sleep(100);
                yield();
        }
}

void
threadmain(int, char**)
{
        threadcreate(noisethread, 0, 32*1024);
        threadcreate(lockthread, 0, 32*1024);
        yield();

        while(sleep(100) != -1){
                qlock(&q);

                /* never gets here */
                print("thread library confused\n");
                yield();
                qunlock(&q);
        }

        threadexitsall("");
}

perhaps qlock should be added to the man page in the
list of yielding functions.

- erik

Reply via email to