umtx_sleep man page on DragonFly

Man page or keyword search:  
man Server   44335 pages
apropos Keyword Search (all sections)
Output format
DragonFly logo
[printable version]

UMTX(2)			    BSD System Calls Manual		       UMTX(2)

NAME
     umtx_sleep, umtx_wakeup — kernel support for userland mutexes

LIBRARY
     Standard C Library (libc, -lc)

SYNOPSIS
     int
     umtx_sleep(const int *ptr, int value, int timeout);

     int
     umtx_wakeup(const int *ptr, int count);

DESCRIPTION
     The umtx_sleep() system call will put the calling process to sleep for
     timeout microseconds if the contents of the specified point matches the
     specified value.  Specifying a timeout of 0 indicates an indefinite time‐
     out.  The comparison is not atomic with the sleep but is properly inter‐
     locked against another process calling umtx_wakeup().  In particular,
     while it is possible for two userland threads to race, one going to sleep
     simultaneously with another releasing the mutex, this condition is caught
     when the second userland thread calls umtx_wakeup() after releasing the
     contended mutex.

     The timeout is not specific limitation other than what fits in the signed
     integer.  A negative timeout will return EINVAL.

     The umtx_wakeup() system call will wakeup the specified number of pro‐
     cesses sleeping in umtx_sleep() on the specified user address.  A count
     of 0 will wake up all sleeping processes.	This function may wake up more
     processes then the specified count but will never wake up fewer processes
     (unless there are simply not that many currently sleeping on the
     address).	The current DragonFly implementation optimized the count = 1
     case but otherwise just wakes up all processes sleeping on the address.

     Kernel support for userland mutexes is based on the physical memory back‐
     ing the user address.  Two userland programs may use this facility
     through mmap(), sysv(), rfork(), or light weight process-based shared
     memory.  It is important to note that the kernel does not take responsi‐
     bility for adjusting the contents of the mutex or for the userland imple‐
     mentation of the mutex.

     umtx_sleep() does not restart in case of a signal, even if the signal
     specifies that system calls should restart.

     Various operating system events can cause umtx_sleep() to return prema‐
     turely, with the contents of the mutex unchanged relative to the compare
     value.  Callers must be able to deal with such returns.

RETURN VALUES
     umtx_sleep() will return 0 if it successfully slept and was then woken
     up.  Otherwise it will return -1 and set errno as shown below.

     umtx_wakeup() will generally return 0 unless the address is bad.

EXAMPLE
     void
     userland_get_mutex(struct umtx *mtx)
     {
	 int v;

	 for (;;) {
	     v = mtx->lock;
	     if ((v & MTX_LOCKED) == 0) {
		 /*
		  * not locked, attempt to lock.
		  */
		 if (cmp_and_exg(&mtx->lock, v, v | MTX_LOCKED) == 0)
		     return;
	     } else {
		 /*
		  * Locked, bump the contested count and obtain the contested
		  * mutex.
		  */
		 if (cmp_and_exg(&mtx->lock, v, v + 1) == 0) {
		     userland_get_mutex_contested(mtx);
		     return;
		 }
	     }
	 }
     }

     static void
     userland_get_mutex_contested(struct umtx *mtx)
     {
	 int v;

	 for (;;) {
	     v = mtx->lock;
	     assert(v & ~MTX_LOCKED);	     /* our contesting count still there */
	     if ((v & MTX_LOCKED) == 0) {
		 /*
		  * not locked, attempt to remove our contested count and
		  * lock at the same time.
		  */
		 if (cmp_and_exg(&mtx->lock, v, (v - 1) | MTX_LOCKED) == 0)
		     return;
	     } else {
		 /*
		  * Still locked, sleep and try again.
		  */
		 umtx_sleep(&mtx->lock, v, 0);
		 /*
		  * XXX note: if we are woken up here but do not proceed to
		  * attempt to obtain the mutex, we should chain the
		  * umtx_wakeup() along.
		  */
	     }
	 }
     }

     void
     userland_rel_mutex(struct umtx *mtx)
     {
	 int v;

	 for (;;) {
	     v = mtx->lock;
	     assert(v & MTX_LOCKED); /* we still have it locked */
	     if (v == MTX_LOCKED) {
		 /*
		  * We hold an uncontested lock, try to set to an unlocked
		  * state.
		  */
		 if (cmp_and_exg(&mtx->lock, MTX_LOCKED, 0) == 0)
		     return;
	     } else {
		 /*
		  * We hold a contested lock, unlock and wakeup exactly
		  * one sleeper.  It is possible for this to race a new
		  * thread obtaining a lock, in which case any contested
		  * sleeper we wake up will simply go back to sleep.
		  */
		 if (cmp_and_exg(&mtx->lock, v, v & ~MTX_LOCKED) == 0) {
		     umtx_wakeup(&mtx->lock, 1);
		     return;
		 }
	     }
	 }
     }

ERRORS
     [EBUSY]		The contents of *ptr did not match value

     [EWOULDBLOCK]	The specified timeout occurred.

     [EINTR]		The umtx_sleep() call was interrupted by a signal.

     [EINVAL]		An invalid parameter (typically an invalid timeout)
			was specified.

SEE ALSO
     tls(2)

HISTORY
     The umtx_sleep(), and umtx_wakeup() function calls first appeared in
     DragonFly 1.1.

BSD			       February 21, 2005			   BSD
[top]

List of man pages available for DragonFly

Copyright (c) for man pages and the logo by the respective OS vendor.

For those who want to learn more, the polarhome community provides shell access and support.

[legal] [privacy] [GNU] [policy] [cookies] [netiquette] [sponsors] [FAQ]
Tweet
Polarhome, production since 1999.
Member of Polarhome portal.
Based on Fawad Halim's script.
....................................................................
Vote for polarhome
Free Shell Accounts :: the biggest list on the net