Add a manual page for the umtx_*() system calls.
authorMatthew Dillon <dillon@dragonflybsd.org>
Mon, 21 Feb 2005 19:53:34 +0000 (19:53 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Mon, 21 Feb 2005 19:53:34 +0000 (19:53 +0000)
lib/libc/sys/Makefile.inc
lib/libc/sys/umtx.2 [new file with mode: 0644]

index 6fd957c..3fd4dd3 100644 (file)
@@ -1,6 +1,6 @@
 #      @(#)Makefile.inc        8.3 (Berkeley) 10/24/94
 # $FreeBSD: src/lib/libc/sys/Makefile.inc,v 1.75.2.7 2003/04/22 17:31:18 trhodes Exp $
-# $DragonFly: src/lib/libc/sys/Makefile.inc,v 1.8 2005/01/31 22:29:59 joerg Exp $
+# $DragonFly: src/lib/libc/sys/Makefile.inc,v 1.9 2005/02/21 19:53:34 dillon Exp $
 
 # sys sources
 .PATH: ${.CURDIR}/../libc/${MACHINE_ARCH}/sys ${.CURDIR}/../libc/sys
@@ -105,7 +105,7 @@ MAN+=       _exit.2 accept.2 access.2 acct.2 adjtime.2 \
        sigaction.2 sigaltstack.2 sigpending.2 sigprocmask.2 sigreturn.2 \
        sigstack.2 sigsuspend.2 socket.2 socketpair.2 stat.2 statfs.2 \
        swapon.2 symlink.2 sync.2 sysarch.2 syscall.2 \
-       truncate.2 umask.2 undelete.2 \
+       truncate.2 umask.2 umtx.2 undelete.2 \
        unlink.2 utimes.2 upc_register.2 vfork.2 wait.2 write.2
 .if !defined(NO_P1003_1B)
 MAN+=  sched_get_priority_max.2 sched_setparam.2 \
diff --git a/lib/libc/sys/umtx.2 b/lib/libc/sys/umtx.2
new file mode 100644 (file)
index 0000000..e766729
--- /dev/null
@@ -0,0 +1,209 @@
+.\" Copyright (c) 2003,2004 The DragonFly Project.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to The DragonFly Project
+.\" by Matthew Dillon <dillon@backplane.com>
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in
+.\"    the documentation and/or other materials provided with the
+.\"    distribution.
+.\" 3. Neither the name of The DragonFly Project nor the names of its
+.\"    contributors may be used to endorse or promote products derived
+.\"    from this software without specific, prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+.\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+.\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+.\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $DragonFly: src/lib/libc/sys/umtx.2,v 1.1 2005/02/21 19:53:34 dillon Exp $
+.\"
+.Dd February 21, 2005
+.Dt UMTX 2
+.Os
+.Sh NAME
+.Nm umtx_sleep ,
+.Nm umtx_wakeup
+.Nd kernel support for userland mutexes
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.Ft int
+.Fn umtx_sleep "const int *ptr" "int value" "int timeout"
+.Ft int
+.Fn umtx_wakeup "const int *ptr" "int count"
+.Sh DESCRIPTION
+The
+.Fn umtx_sleep
+system call will put the calling process to sleep for
+.Fa timeout
+microseconds if the contents of the specified point matches 
+the specified value.
+Specifying a timeout of 0 indicates an indefinite timeout.
+The comparison is not atomic with the sleep but is properly
+interlocked against another process calling
+.Fn umtx_wakeup .
+In particular, while it is possible for two userland threads to race, one
+going to sleep simultaniously with another releasing the mutex, this condition
+is caught when the second userland thread calls
+.Fn umtx_wakeup
+after releasing the contended mutex.
+The
+.Fa timeout
+is limited to the range 0-1000000 microseconds.
+.Pp
+The
+.Fn umtx_wakeup
+system call will wakeup the specified number of processes sleeping
+in
+.Fn 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.
+.Pp
+Kernel support for userland mutexes is based on the physical memory backing
+the user address.  Two userland programs may use this facility through
+.Fn mmap ,
+.Fn sysv ,
+and
+.Fn rfork
+based shared memory.  It is important to note that the kernel does not
+take responsibility for adjusting the contents of the mutex or for the
+userland implementation of the mutex.
+.Sh RETURN VALUES
+.Fn umtx_sleep
+will return 0 if it successfully slept and was then woken up.  Otherwise
+it will return -1 and set
+.Li errno
+as shown below.
+.Pp
+.Fn umtx_wakeup
+will generally return 0 unless the address is bad. 
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EBUSY
+The contents of
+.Fa *ptr
+did not match
+.Fa value
+.It Bq Er ETIMEDOUT
+The specified timeout occured.
+.It Bq Er EINTR
+The
+.Fn umtx_sleep
+call was interrupted by a signal.
+.It Bq Er EINVAL
+An invalid parameter (typically an invalid timeout) was specified.
+.Sh EXAMPLE
+.Bd -literal -compact
+
+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;
+           }
+       }
+    }
+}
+.Ed
+
+.Sh SEE ALSO
+.Sh HISTORY
+The
+.Fn umtx_sleep ,
+and
+.Fn umtx_wakeup
+function calls first appeared in DragonFly 1.1 .