From 791e9ddbec849e9a9ec318fdcf5ccd911c696587 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Mon, 21 Feb 2005 19:53:34 +0000 Subject: [PATCH] Add a manual page for the umtx_*() system calls. --- lib/libc/sys/Makefile.inc | 4 +- lib/libc/sys/umtx.2 | 209 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 211 insertions(+), 2 deletions(-) create mode 100644 lib/libc/sys/umtx.2 diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc index 6fd957c1f3..3fd4dd35a3 100644 --- a/lib/libc/sys/Makefile.inc +++ b/lib/libc/sys/Makefile.inc @@ -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 index 0000000000..e766729ddd --- /dev/null +++ b/lib/libc/sys/umtx.2 @@ -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 +.\" +.\" 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 . -- 2.41.0