Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages


home | help
LOCK(3)			   Library Functions Manual		       LOCK(3)

       lock,  canlock, unlock, qlock, canqlock,	qunlock, rlock,	canrlock, run-
       lock, wlock, canwlock, wunlock, rsleep, rwakeup,	rwakeupall incref, de-
       cref - spin locks, queueing rendezvous locks, reader-writer locks, ren-
       dezvous points, and reference counts

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

       void lock(Lock *l)
       int  canlock(Lock *l)
       void unlock(Lock	*l)

       void qlock(QLock	*l)
       int  canqlock(QLock *l)
       void qunlock(QLock *l)

       void rlock(RWLock *l)
       int  canrlock(RWLock *l)
       void runlock(RWLock *l)

       void wlock(RWLock *l)
       int  canwlock(RWLock *l)
       void wunlock(RWLock *l)

       typedef struct Rendez {
	    QLock *l;
       } Rendez;

       void rsleep(Rendez *r)
       int  rwakeup(Rendez *r)
       int  rwakeupall(Rendez *r)

       #include	<thread.h>

       typedef struct Ref {
	    long ref;
       } Ref;

       void incref(Ref*)
       long decref(Ref*)

       These routines are used	to synchronize processes sharing memory.

       Locks are spin locks, QLocks and	RWLocks	are different types of	queue-
       ing locks, and Rendezes are rendezvous points.

       Locks  and  rendezvous  points have trivial implementations in programs
       not using the thread library (see since such programs have  no  concur-

       Used  carelessly,  spin	locks can be expensive and can easily generate
       deadlocks.  Their use is	discouraged, especially	in programs  that  use
       the  thread  library  because  they  prevent  context  switches between

       Lock blocks until the lock has been obtained.  Canlock is non-blocking.
       It  tries  to obtain a lock and returns a non-zero value	if it was suc-
       cessful,	0 otherwise.  Unlock releases a	lock.

       QLocks have the same interface but are not spin locks; instead  if  the
       lock  is	taken qlock will suspend execution of the calling thread until
       it is released.

       Although	Locks are the more primitive lock, they	have limitations;  for
       example,	 they  cannot synchronize between tasks	in the same proc.  Use
       QLocks instead.

       RWLocks manage access to	a data structure that has distinct readers and
       writers.	  Rlock	grants read access; runlock releases it.  Wlock	grants
       write access; wunlock releases it.  Canrlock and	canwlock are the  non-
       blocking	 versions.   There  may	be any number of simultaneous readers,
       but only	one writer.  Moreover, if write	access is granted no  one  may
       have read access	until write access is released.

       All  types  of lock should be initialized to all	zeros before use; this
       puts them in the	unlocked state.

       Rendezes	are rendezvous points.	Each Rendez r is protected by a	 QLock
       r->l, which must	be held	by the callers of rsleep, rwakeup, and rwakeu-
       pall.  Rsleep atomically	releases r->l and suspends  execution  of  the
       calling task.  After resuming execution,	rsleep will reacquire r->l be-
       fore returning.	If any processes are sleeping on r, rwakeup wakes  one
       of them.	 It returns 1 if a process was awakened, 0 if not.  Rwakeupall
       wakes all processes sleeping on r, returning the	 number	 of  processes
       awakened.   Rwakeup  and	rwakeupall do not release r->l and do not sus-
       pend execution of the current task.

       Before use, Rendezes should be initialized to all zeros except for r->l
       pointer,	which should point at the QLock	that will guard	r.

       A  Ref  contains	 a long	that can be incremented	and decremented	atomi-
       cally: Incref increments	the Ref	in one atomic operation.  Decref atom-
       ically  decrements  the	Ref and	returns	zero if	the resulting value is
       zero, non-zero otherwise.


       Locks are not always spin locks.	 Instead they are usually  implemented
       using  the  pthreads  library's	pthread_mutex_t,  whose	implementation
       method is not defined.

       On pthreads-based systems,  the	implementation	of  Lock  never	 calls
       pthread_mutex_destroy to	free the pthread_mutex_t's.  This leads	to re-
       source leaks on FreeBSD 5 (though not on	Linux 2.6,  where  pthread_mu-
       tex_destroy is a	no-op).

       On  systems that	do not have a usable pthreads implementation, the Lock
       implementation provided by libthread is still not exactly a spin	 lock.
       After  each unsuccessful	attempt, lock calls sleep(0) to	yield the CPU;
       this handles the	common case where some other process holds  the	 lock.
       After  a	 thousand unsuccessful attempts, lock sleeps for 100ms between
       attempts.  Another another thousand unsuccessful	attempts, lock	sleeps
       for  a full second between attempts.  Locks are not intended to be held
       for long	periods	of time.  The 100ms and	full second  sleeps  are  only
       heuristics to avoid tying up the	CPU when a process deadlocks.  As dis-
       cussed above, if	a lock is to be	held for much more than	a few instruc-
       tions, the queueing lock	types should be	almost always be used.



Want to link to this manual page? Use this URL:

home | help