Changeset View
Standalone View
lib/libc/sys/_umtx_op.2
- This file was added.
.\" Copyright (c) 2016 The FreeBSD Foundation, Inc. | |||||
.\" All rights reserved. | |||||
.\" | |||||
.\" This documentation was written by | |||||
.\" Konstantin Belousov <kib@FreeBSD.org> under sponsorship | |||||
.\" from the FreeBSD Foundation. | |||||
.\" | |||||
.\" 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. | |||||
.\" | |||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. | |||||
.\" | |||||
.\" $FreeBSD$ | |||||
.\" | |||||
.Dd May 5, 2016 | |||||
.Dt _UMTX_OP 2 | |||||
.Os | |||||
.Sh NAME | |||||
.Nm _umtx_op | |||||
.Nd interface for implementation of userspace threading synchronization primitives | |||||
.Sh LIBRARY | |||||
.Lb libc | |||||
.Sh SYNOPSIS | |||||
.In sys/types.h | |||||
.In sys/umtx.h | |||||
.Ft int | |||||
.Fn _umtx_op "void *obj" "int op" "u_long val" "void *uaddr" "void *uaddr2" | |||||
.Sh DESCRIPTION | |||||
The | |||||
.Fn _umtx_op | |||||
system call provides kernel support for userspace implementation of | |||||
the threading synchronization primitives. | |||||
The | |||||
.Lb libthr | |||||
uses the syscall to implement | |||||
.St -p1003.1-2001 | |||||
pthread locks, like mutexes, condition variables and so on. | |||||
.Ss STRUCTURES | |||||
The operations, performed by the | |||||
.Fn _umtx_op | |||||
syscall, operate on userspace objects which are described | |||||
by the following structures. | |||||
emaste: I would drop the 'the' and second comma (before which are)
| |||||
Reserved fields and paddings are omitted. | |||||
All objects require ABI-mandated alignment, but this is not currently | |||||
enforced consistently on all architectures. | |||||
.Pp | |||||
The following flags are defined for flag fields of all structures: | |||||
.Bl -tag -width "Dv USYNC_PROCESS_SHARED" | |||||
.It Dv USYNC_PROCESS_SHARED | |||||
Allow selection of the process-shared sleep queue for the thread sleep | |||||
container, when the lock ownership cannot be granted immediately, | |||||
and the operation must sleep. | |||||
The process-shared or process-private sleep queue is selected based on | |||||
the attributes of the memory mapping which contains the first byte of | |||||
the structure, see | |||||
.Xr mmap 2 . | |||||
Otherwise, if the flag is not specified, the process-private sleep queue | |||||
is selected regardless of the memory mapping attributes, as an optimization. | |||||
.Pp | |||||
Done Inline Actionsas an optimization emaste: as an optimization | |||||
See the | |||||
.Sx SLEEP QUEUES | |||||
subsection below for more details on sleep queues. | |||||
.El | |||||
Done Inline ActionsSee the SLEEP QUEUES subsection below for more emaste: See the SLEEP QUEUES subsection below for more
| |||||
.Pp | |||||
.Bl -hang -offset indent | |||||
.It Sy Mutex | |||||
.Bd -literal | |||||
struct umutex { | |||||
volatile lwpid_t m_owner; | |||||
uint32_t m_flags; | |||||
uint32_t m_ceilings[2]; | |||||
}; | |||||
.Ed | |||||
.Pp | |||||
The | |||||
.Dv m_owner | |||||
field is the actual lock. | |||||
It contains either the thread identifier of the lock owner in the | |||||
locked state, or zero when the lock is unowned. | |||||
The highest bit set indicates that there is contention on the lock. | |||||
The constants are defined for special values: | |||||
.Bl -tag -width "Dv UMUTEX_CONTESTED" | |||||
.It Dv UMUTEX_UNOWNED | |||||
Zero, the value stored in the unowned lock. | |||||
.It Dv UMUTEX_CONTESTED | |||||
The contenion indicator. | |||||
.El | |||||
.Pp | |||||
The | |||||
.Dv m_flags | |||||
field may contain the following umutex-specific flags, in addition to | |||||
the common flags: | |||||
.Bl -tag -width "Dv UMUTEX_PRIO_INHERIT" | |||||
.It Dv UMUTEX_PRIO_INHERIT | |||||
Mutex implements | |||||
.Em Priority Inheritance | |||||
protocol. | |||||
.It Dv UMUTEX_PRIO_PROTECT | |||||
Mutex implements | |||||
.Em Priority Protection | |||||
protocol. | |||||
.El | |||||
.Pp | |||||
In the manual page, mutexes not having | |||||
.Dv UMUTEX_PRIO_INHERIT | |||||
Not Done Inline ActionsIn this manual page? emaste: In this manual page?
(Or, true in general?) | |||||
Not Done Inline Actionsumutex != posix mutex, umutex is a substrate used to implement posix mutex semantic. POSIX calls normal mutexes one with default behaviour, i.e. non-recursive and usually non error-checking (ours normal are error checking). I need some short term for non-pp/pi umutexes. kib: umutex != posix mutex, umutex is a substrate used to implement posix mutex semantic.
POSIX… | |||||
Not Done Inline ActionsAh, of course. So probably "this manual page" is best. emaste: Ah, of course. So probably "this manual page" is best. | |||||
and | |||||
.Dv UMUTEX_PRIO_PROTECT | |||||
flags set, are called normal mutexes. | |||||
Each type of mutex, i.e. normal mutexes, priority-inherited mutexes, | |||||
and priority-protected mutexes, have a separate sleep queue associated | |||||
Done Inline ActionsEach type of mutex, emaste: Each type of mutex, | |||||
with the given key. | |||||
.Pp | |||||
For priority protected mutexes, the | |||||
.Dv m_ceilings | |||||
Done Inline Actionsprotected mutexes, the emaste: protected mutexes, the | |||||
array contains priority ceiling values. | |||||
The | |||||
.Dv m_ceilings[0] | |||||
is the ceiling value for the mutex, as specified by | |||||
.St -p1003.1-2008 | |||||
for the | |||||
.Em Priority Protected | |||||
mutex protocol. | |||||
The | |||||
.Dv m_ceilings[1] | |||||
is used only for the unlock of a priority protected mutex, when | |||||
unlock is done in an order other than the reversed lock order. | |||||
Not Done Inline Actionsfor the unlock of a priority emaste: for the unlock of a priority
(or for unlocking a priority protected) | |||||
In this case, | |||||
Not Done Inline Actionsan order other than emaste: an order other than | |||||
.Dv m_ceilings[1] | |||||
must contain the ceiling value for the last locked priority protected | |||||
mutex, for proper priority reassignment. | |||||
If, instead, the unlocking mutex was the last priority propagated | |||||
mutex locked by the thread, | |||||
Done Inline ActionsCan this be clarified? I can't really follow. emaste: Can this be clarified? I can't really follow. | |||||
Not Done Inline ActionsI mean that lock was done in order A then B then C, and we unlock B. In this case, B.m_ceilings[1] must contain C.m_ceilings[0]. Hopefully, my reformulation will be clearer. kib: I mean that lock was done in order A then B then C, and we unlock B. In this case, B. | |||||
Not Done Inline ActionsOk emaste: Ok | |||||
.Dv m_ceilings[1] | |||||
should contain \-1. | |||||
This is required because kernel does not maintain the ordered lock list. | |||||
.It Sy Condition variable | |||||
.Bd -literal | |||||
struct ucond { | |||||
Done Inline Actionscondition variable? emaste: condition variable? | |||||
volatile uint32_t c_has_waiters; | |||||
uint32_t c_flags; | |||||
uint32_t c_clockid; | |||||
}; | |||||
.Ed | |||||
.Pp | |||||
A non-zero | |||||
.Dv c_has_waiters | |||||
value indicates that there are in-kernel waiters for the condition, | |||||
executing the | |||||
.Dv UMTX_OP_CV_WAIT | |||||
Done Inline ActionsI'd probably write "A non-zero c_has_waiters value indicates..." emaste: I'd probably write "A non-zero c_has_waiters value indicates..." | |||||
request. | |||||
.Pp | |||||
The | |||||
.Dv c_flags | |||||
field contains flags. | |||||
Only the common flags, i.e. | |||||
.Dv USYNC_PROCESS_SHARED , | |||||
are defined for ucond. | |||||
.Pp | |||||
The | |||||
.Dv c_clockid | |||||
member provides the clock identifier to use for timeout, when the | |||||
.Dv UMTX_OP_CV_WAIT | |||||
request has both the | |||||
.Dv CVWAIT_CLOCKID | |||||
flag and the timeout specified. | |||||
Done Inline Actionshas both the CVWAIT_CLOCKID flag and the timeout specified emaste: has both the CVWAIT_CLOCKID flag and the timeout specified
(in other cases I'd omit the second… | |||||
Valid clock identifiers are subset of the valid clock ids for the | |||||
.Xr clock_gettime 2 | |||||
syscall, namely, | |||||
.Dv CLOCK_REALTIME , | |||||
.Dv CLOCK_VIRTUAL , | |||||
.Dv CLOCK_PROF , | |||||
.Dv CLOCK_MONOTONIC , | |||||
.Dv CLOCK_UPTIME , | |||||
.Dv CLOCK_UPTIME_PRECISE , | |||||
.Dv CLOCK_UPTIME_FAST , | |||||
.Dv CLOCK_REALTIME_PRECISE , | |||||
.Dv CLOCK_REALTIME_FAST , | |||||
.Dv CLOCK_MONOTONIC_PRECISE , | |||||
.Dv CLOCK_MONOTONIC_FAST , | |||||
and | |||||
.Dv CLOCK_SECOND | |||||
are allowed. | |||||
.It Sy Reader/writer lock | |||||
.Bd -literal | |||||
struct urwlock { | |||||
volatile int32_t rw_state; | |||||
uint32_t rw_flags; | |||||
uint32_t rw_blocked_readers; | |||||
uint32_t rw_blocked_writers; | |||||
}; | |||||
.Ed | |||||
.Pp | |||||
The | |||||
.Dv rw_state | |||||
field is the actual lock. | |||||
It contains both the flags and counter of the read locks which were | |||||
granted. | |||||
Names of the | |||||
.Dv rw_state | |||||
bits are following: | |||||
.Bl -tag -width "Dv URWLOCK_WRITE_WAITERS" | |||||
.It Dv URWLOCK_WRITE_OWNER | |||||
Write lock was granted. | |||||
.It Dv URWLOCK_WRITE_WAITERS | |||||
There are write lock waiters. | |||||
.It Dv URWLOCK_READ_WAITERS | |||||
There are read lock waiters. | |||||
.It Dv URWLOCK_READER_COUNT(c) | |||||
Returns the count of currently granted read locks. | |||||
.El | |||||
.Pp | |||||
At any given time there may be only one thread to which the writer lock | |||||
is granted on the | |||||
Done Inline Actionssomething still missing here emaste: something still missing here | |||||
.Vt struct rwlock , | |||||
Done Inline ActionsAt any given time there may be only one thread ... emaste: At any given time there may be only one thread ... | |||||
and no threads are granted read lock. | |||||
Or, at the given time, up to | |||||
.Dv URWLOCK_MAX_READERS | |||||
threads may be granted the read lock simultaneously, but write lock is | |||||
not granted to any thread. | |||||
.Pp | |||||
The following flags for the | |||||
.Dv rw_flags | |||||
member of | |||||
.Vt struct urwlock | |||||
are defined, in addition to the common flags: | |||||
.Bl -tag -width "Dv URWLOCK_PREFER_READER" | |||||
.It Dv URWLOCK_PREFER_READER | |||||
If specified, immediately grant read lock requests when | |||||
.Dv urwlock | |||||
is already read-locked, even in presence of the unsatisfied write | |||||
lock requests. | |||||
By default, if there is a write lock waiter, further read requests are | |||||
not granted, to prevent unfair write lock waiter starvation. | |||||
.El | |||||
.Pp | |||||
The | |||||
.Dv rw_blocked_readers | |||||
and | |||||
.Dv rw_blocked_writers | |||||
members contain the count of threads which are sleeping in kernel, | |||||
waiting for the associated request type to be granted. | |||||
The fields are used by kernel to update the | |||||
Done Inline ActionsMaybe something like this? emaste: Maybe something like this?
the count of threads which are sleeping in kernel, waiting for the… | |||||
.Dv URWLOCK_READ_WAITERS | |||||
and | |||||
.Dv URWLOCK_WRITE_WAITERS | |||||
flags of the | |||||
.Dv rw_state | |||||
lock after requesting thread was woken up. | |||||
.It Sy Semaphore | |||||
.Bd -literal | |||||
struct _usem2 { | |||||
volatile uint32_t _count; | |||||
uint32_t _flags; | |||||
}; | |||||
.Ed | |||||
.Pp | |||||
The | |||||
.Dv _count | |||||
word represents a counting semaphore. | |||||
A non-zero value indicates an unlocked (posted) semaphore, while zero | |||||
represents the locked state. | |||||
The maximal supported semaphore count is | |||||
Done Inline ActionsA non-zero ... an unlocked (posted) semaphore emaste: A non-zero ... an unlocked (posted) semaphore | |||||
.Dv USEM_MAX_COUNT . | |||||
.Pp | |||||
The | |||||
.Dv _count | |||||
word, besides the counter of posts (unlocks), also contains the | |||||
.Dv USEM_HAS_WAITERS | |||||
bit, which indicates that locked semaphore has waiting threads. | |||||
.Pp | |||||
The | |||||
.Dv USEM_COUNT() | |||||
macro, applied to the | |||||
.Dv _count | |||||
word, returns the current semaphore counter, i.e. the number of posts | |||||
issued on the semaphore. | |||||
.Pp | |||||
The following bits for the | |||||
.Dv _flags | |||||
member of | |||||
.Vt struct _usem2 | |||||
are defined, in addition to the common flags: | |||||
.Bl -tag -width "Dv USEM_NAMED" | |||||
.It Dv USEM_NAMED | |||||
Flag is ignored by kernel. | |||||
.El | |||||
.It Sy Timeout parameter | |||||
.Bd -literal | |||||
struct _umtx_time { | |||||
struct timespec _timeout; | |||||
uint32_t _flags; | |||||
uint32_t _clockid; | |||||
}; | |||||
.Ed | |||||
.Pp | |||||
Several | |||||
.Fn _umtx_op | |||||
operations allow the blocking time to be limited, failing the request | |||||
if it cannot be satisfied in the specified time period. | |||||
The timeout is specified by passing either the address of | |||||
Done Inline Actionsallow the caller to limit the blocking or allow the blocking time to be limited emaste: allow the caller to limit the blocking
or
allow the blocking time to be limited
| |||||
.Vt struct timespec , | |||||
or its extended variant, | |||||
.Vt struct _umtx_time , | |||||
as the | |||||
.Fa uaddr2 | |||||
argument of | |||||
.Fn _umtx_op . | |||||
They are distinguished by the | |||||
.Fa uaddr | |||||
value, which must be equal to the size of the structure pointed to by | |||||
.Fa uaddr2 , | |||||
casted to | |||||
.Vt uintptr_t . | |||||
.Pp | |||||
The | |||||
.Dv _timeout | |||||
member specifies the time when the timeout should occur. | |||||
Legal values for clock identifier | |||||
.Dv _clockid | |||||
are shared with the | |||||
.Fa clock_id | |||||
argument to the | |||||
.Xr clock_gettime 2 | |||||
function, | |||||
and use the same underlying clocks. | |||||
The specified clock is used to obtain the current time value. | |||||
Interval counting is always performed by the monotonic wall clock. | |||||
.Pp | |||||
The | |||||
Done Inline ActionsSeparate sentence? time value. Interval counting is... emaste: Separate sentence? time value. Interval counting is... | |||||
.Dv _flags | |||||
argument allows the following flags to further define the timeout behaviour: | |||||
.Bl -tag -width "It Dv UMTX_ABSTIME" | |||||
.It Dv UMTX_ABSTIME | |||||
The | |||||
.Dv _timeout | |||||
value is the absolute time. | |||||
The thread will be unblocked and the request failed when specified | |||||
clock value is equal or exceeds the | |||||
.Dv _timeout. | |||||
.Pp | |||||
Done Inline ActionsThe thread will be unblocked and the request failed when ... emaste: The thread will be unblocked and the request failed when ... | |||||
If the flag is absent, the timeout value is relative, that is the amount | |||||
of time, measured by the monotonic wall clock from the moment of the request | |||||
start. | |||||
.El | |||||
.El | |||||
.Ss SLEEP QUEUES | |||||
.Pp | |||||
When the locking request cannot be immediately satisfied, for non-try | |||||
emasteUnsubmitted Done Inline ActionsPerhaps just leave the try variant out of the first sentence, and if necessary describe it in a separate sentence? Something like: When a locking request cannot be immediately satisfied the thread is typically put to sleep, which is a non-runnable state terminated by the wake operation. (Most?) Lock operations include a _try variant which returns an error rather than sleeping if the lock cannot be obtained. emaste: Perhaps just leave the try variant out of the first sentence, and if necessary describe it in a… | |||||
requests the thread is typically put to | |||||
.Em sleep , | |||||
which is a non-runnable state, terminated by | |||||
.Em wake | |||||
operation. | |||||
Also, | |||||
.Fn _umtx_op | |||||
provides requests which explicitely put the thread to sleep. | |||||
.Pp | |||||
Wakes need to know which threads to make runnable, so sleeping threads | |||||
are grouped into containers called | |||||
.Em sleep queues . | |||||
Sleep queue is identified by a key, which for | |||||
emasteUnsubmitted Not Done Inline ActionsA sleep queue emaste: **A** sleep queue | |||||
.Fn _umtx_op | |||||
is defined as the physical address of some variable. | |||||
Note that the | |||||
.Em physical | |||||
address is used, which means that same variable mapped multiple | |||||
times, will give one key value. | |||||
emasteUnsubmitted Done Inline Actionscan omit the , here emaste: can omit the , here | |||||
This mechanism enables construction of the | |||||
emasteUnsubmitted Done Inline Actionsenables the construction of process-shared locks. emaste: enables **the** construction of process-shared locks. | |||||
.Em process-shared | |||||
locks. | |||||
.Pp | |||||
Related attribute of the key is shareability. | |||||
emasteUnsubmitted Done Inline ActionsA related emaste: **A** related | |||||
Some requests always interpet keys as private for the current process, | |||||
creating sleep queue with the scope of the current process even if | |||||
emasteUnsubmitted Done Inline Actionscreating sleep queues emaste: creating sleep queue**s**
| |||||
the memory is shared. | |||||
Others either select the shareability automatically from the | |||||
mapping attributes, or take additional input as the | |||||
.Dv USYNC_PROCESS_SHARED | |||||
common flag. | |||||
This is done as optimization, allowing to limit lock scope | |||||
emasteUnsubmitted Done Inline Actionsallowing the lock scope to be limited regardless emaste: allowing **the lock scope to be limited** regardless | |||||
regardless of the kind of backing memory. | |||||
.Pp | |||||
Only the address of the start of the variable specified as key is | |||||
emasteUnsubmitted Done Inline ActionsI'm not sure "start of" is necessary, it should be clear from context (and there is an example below). emaste: I'm not sure "start of" is necessary, it should be clear from context (and there is an example… | |||||
kibAuthorUnsubmitted Not Done Inline ActionsI reformulated this by adding 'byte', i.e. ... the address of the start byte ...'. kib: I reformulated this by adding 'byte', i.e. ... the address of the start byte ...'.
I can write… | |||||
emasteUnsubmitted Not Done Inline ActionsOh, I see. OK. emaste: Oh, I see. OK. | |||||
important for determining corresponding sleep queue. | |||||
The size of the variable does not matter, so e.g. sleep on the same | |||||
address interpeted as | |||||
.Vt uint32_t | |||||
and | |||||
.Vt long | |||||
on little-endian 64-bit platform would collide. | |||||
emasteUnsubmitted Done Inline Actionson a little-endian emaste: on **a** little-endian | |||||
.Pp | |||||
The last attribute of the key is the object type. | |||||
Sleep queue to which sleeping thread is assigned, are individual for | |||||
emasteUnsubmitted Done Inline ActionsThe sleep queue to which a sleeping thread is assigned is individual emaste: **The** sleep queue to which **a** sleeping thread is assigned **is** individual
or even **is… | |||||
simple wait requests, mutexes, rwlocks, condvars and other primitives, | |||||
even when the physical address of the key is same. | |||||
.Pp | |||||
When waking up limited number of threads from the given sleep queue, | |||||
emasteUnsubmitted Done Inline Actionsup a limited number of threads from a given sleep queue emaste: up **a** limited number of threads from **a** given sleep queue | |||||
the highest priority threads that has been blocked for the longest on | |||||
emasteUnsubmitted Done Inline Actionsthat have been emaste: that **have** been | |||||
the queue are selected. | |||||
.Ss OPERATIONS | |||||
The following operations, requested by the | |||||
.Fa op | |||||
argument to the function, are implemented: | |||||
.Bl -tag -width "It Dv UMTX_OP_WAIT_UINT_PRIVATE" | |||||
.It Dv UMTX_OP_WAIT | |||||
Wait. | |||||
The arguments for the request are: | |||||
.Bl -tag -width "It Fa obj" | |||||
.It Fa obj | |||||
Pointer to a variable of type | |||||
.Vt long . | |||||
.It Fa val | |||||
Current value of the | |||||
.Dv *obj . | |||||
.El | |||||
.Pp | |||||
The current value of the variable pointed to by the | |||||
.Fa obj | |||||
argument is compared with the | |||||
.Fa val . | |||||
If they are equal, requesting thread is put to interruptible sleep | |||||
emasteUnsubmitted Done Inline Actionsequal, the requesting emaste: equal, **the** requesting | |||||
until woken up or optionally specified timeout expires. | |||||
emasteUnsubmitted Done Inline Actionsor the optionally specified emaste: or **the** optionally specified | |||||
.Pp | |||||
The comparision and sleep are atomic. | |||||
In other words, if other thread writes new value to | |||||
emasteUnsubmitted Done Inline Actionsif another thread writes a new value emaste: if **another** thread writes **a** new value | |||||
.Dv *obj | |||||
and then issues | |||||
.Dv UMTX_OP_WAKE , | |||||
then the request is guaranteed to not miss the wakeup, | |||||
emasteUnsubmitted Done Inline Actionsomit then (because it seems awkward with the previous one in and then issues) and then issues UMTX_OP_WAKE, the request is emaste: omit then (because it seems awkward with the previous one in and then issues)
and then issues… | |||||
which might otherwise happen between comparision and blocking. | |||||
.Pp | |||||
The physical address of memory where the | |||||
.Fa *obj | |||||
variable is located, is used as a key to index sleeping threads. | |||||
.Pp | |||||
The read of the current value of the | |||||
.Dv *obj | |||||
variable is not guarded by barriers. | |||||
emasteUnsubmitted Done Inline ActionsMight be worth expanding on this with one more sentence (e.g. mentioning what this implies / why it's important). emaste: Might be worth expanding on this with one more sentence (e.g. mentioning what this implies /… | |||||
.Pp | |||||
The request is not restartable, an unblocked signal delivered during | |||||
emasteUnsubmitted Done Inline Actionsnot restartable. An unblocked signal... emaste: not restartable**. An** unblocked signal... | |||||
the wait always results in sleep interruption and | |||||
.Er EINTR | |||||
error. | |||||
.Pp | |||||
Done Inline ActionsMight be more clear as: user's duty ... emaste: Might be more clear as:
user**'s** duty ...
ensure lock acquire and release memory **semantics… | |||||
Optionally, a timeout for the request may be specified. | |||||
.It Dv UMTX_OP_WAKE | |||||
Wake the threads possibly sleeping due to | |||||
.Dv UMTX_OP_WAIT . | |||||
The arguments for the request are: | |||||
Done Inline Actionsa simple lock emaste: **a** simple lock
| |||||
.Bl -tag -width "It Fa obj" | |||||
.It Fa obj | |||||
Pointer to a variable, used as a key to find threads sleeping. | |||||
emasteUnsubmitted Done Inline Actionsprobably "sleeping threads" rather than "threads sleeping" emaste: probably "sleeping threads" rather than "threads sleeping" | |||||
.It Fa val | |||||
Up to | |||||
.Fa val | |||||
threads is woken up by this request. | |||||
emasteUnsubmitted Done Inline Actionsthreads are woken emaste: threads **are** woken | |||||
Specify | |||||
.Dv INT_MAX | |||||
to wake up all waiters. | |||||
.El | |||||
.It Dv UMTX_OP_MUTEX_TRYLOCK | |||||
Try to lock umutex. | |||||
The arguments to the request are: | |||||
.Bl -tag -width "It Fa obj" | |||||
.It Fa obj | |||||
Pointer to the umutex. | |||||
.El | |||||
.Pp | |||||
Operates same as the | |||||
.Dv UMTX_OP_MUTEX_LOCK | |||||
request, but returns | |||||
.Er EBUSY | |||||
instead of sleeping if the lock cannot be obtained immediately. | |||||
.It Dv UMTX_OP_MUTEX_LOCK | |||||
Lock umutex. | |||||
The arguments to the request are: | |||||
.Bl -tag -width "It Fa obj" | |||||
.It Fa obj | |||||
Pointer to the umutex. | |||||
.El | |||||
.Pp | |||||
Locking is performed by writing the current thread id into the | |||||
.Dv m_owner | |||||
word of the | |||||
.Vt struct umutex . | |||||
The write is atomic, preserves the | |||||
.Dv UMUTEX_CONTESTED | |||||
contention indicator, and provides the acquire barrier for | |||||
lock entrance semantic. | |||||
.Pp | |||||
If the lock cannot be obtained immediately, due to another thread | |||||
emasteUnsubmitted Done Inline ActionsThis seems long/awkward. Since you explain that the thread id is stored in m_owner it's probably clear that someone else owning the lock has their thread id in m_owner. So maybe just: If the lock cannot be obtained immediately because another thread owns the lock, the current thread is put into sleep, with UMUTEX_CONTESTED bit set before. emaste: This seems long/awkward. Since you explain that the thread id is stored in m_owner it's… | |||||
claiming the lock ownership by having the other thread id written | |||||
into the | |||||
.Dv m_owner | |||||
word of the structure, the current thread is put into sleep, with | |||||
.Dv UMUTEX_CONTESTED | |||||
bit set before. | |||||
Upon wake up, the lock conditions are re-tested. | |||||
.Pp | |||||
The request adheres to the priority protection or inheritance protocol | |||||
of the mutex, specified by the | |||||
.Dv UMUTEX_PRIO_PROTECT | |||||
or | |||||
.Dv UMUTEX_PRIO_INHERIT | |||||
flag, respectively. | |||||
.Pp | |||||
Optionally, a timeout for the request may be specified. | |||||
.Pp | |||||
The request with a timeout specified is not restartable, an unblocked | |||||
emasteUnsubmitted Done Inline ActionsA request with .. not restartable. An unblocked emaste: **A** request with .. not restartable**. An **unblocked | |||||
signal delivered during the wait always results in sleep interruption and | |||||
.Er EINTR | |||||
error. | |||||
The request without timeout specified is always restarted after return | |||||
emasteUnsubmitted Done Inline ActionsA request without emaste: **A** request without | |||||
from the signal handler. | |||||
emasteUnsubmitted Done Inline Actionsfrom a signal handler emaste: from **a** signal handler | |||||
.It Dv UMTX_OP_MUTEX_UNLOCK | |||||
Unlock umutex. | |||||
The arguments to the request are: | |||||
.Bl -tag -width "It Fa obj" | |||||
.It Fa obj | |||||
Pointer to the umutex. | |||||
.El | |||||
.Pp | |||||
Unlocks the mutex, by writing | |||||
.Dv UMUTEX_UNOWNED | |||||
(zero) value into | |||||
.Dv m_owner | |||||
word of the | |||||
.Vt struct umutex . | |||||
Write is done with the release barrier, to provide lock leave semantic. | |||||
emasteUnsubmitted Done Inline ActionsThe write is done with a release emaste: **The** write is done with **a** release | |||||
.Pp | |||||
If there are threads sleeping in the sleep queue associated with the | |||||
umutex, one thread is woken up. | |||||
If more than one thread sleeps in the sleep queue, the | |||||
.Dv UMUTEX_CONTESTED | |||||
bit is set together with the write of the | |||||
.Dv UMUTEX_UNOWNED | |||||
value into | |||||
.Dv m_owner . | |||||
.Pp | |||||
The request adheres to the priority protection or inheritance protocol | |||||
of the mutex, specified by the | |||||
.Dv UMUTEX_PRIO_PROTECT | |||||
or | |||||
.Dv UMUTEX_PRIO_INHERIT | |||||
flag, respectively. | |||||
See description of the | |||||
.Dv m_ceilings | |||||
member of the | |||||
.Vt struct umutex | |||||
structure for additional details of the request operation on the | |||||
priority protected protocol mutex. | |||||
.It Dv UMTX_OP_SET_CEILING | |||||
Set ceiling for the priority protected umutex. | |||||
The arguments to the request are: | |||||
.Bl -tag -width "It Fa obj" | |||||
.It Fa obj | |||||
Pointer to the umutex. | |||||
.It Fa val | |||||
New ceiling value. | |||||
.It Fa uaddr1 | |||||
Address of a variable of type | |||||
.Vt uint32_t . | |||||
If not NULL, after the successful update, previous ceiling value is | |||||
emasteUnsubmitted Done Inline Actionssuccessful update the previous emaste: successful update **the** previous | |||||
written to the location pointed to by | |||||
.Fa uaddr1 . | |||||
.El | |||||
.Pp | |||||
The request locks umutex pointed to by the | |||||
emasteUnsubmitted Done Inline Actionslocks the umutex emaste: locks **the** umutex | |||||
.Fa obj | |||||
parameter, waiting for the lock if not immediately available. | |||||
After the lock is obtained, new ceiling value | |||||
emasteUnsubmitted Not Done Inline Actions, the new ceiling emaste: , **the** new ceiling | |||||
.Fa val | |||||
is written to the | |||||
.Dv m_ceilings[0] | |||||
member of the | |||||
.Vt struct umutex, | |||||
after which the umutex is unlocked. | |||||
.Pp | |||||
The locking does not adhere to the priority protect protocol. | |||||
emasteUnsubmitted Done Inline ActionsPerhaps emphasize not, or explain further (e.g. does not adhere ... because ...) emaste: Perhaps emphasize not, or explain further (e.g. does not adhere ... because ...) | |||||
.It Dv UMTX_OP_CV_WAIT | |||||
Wait for a condition. | |||||
Not Done Inline Actionsmissed this one emaste: missed this one | |||||
Not Done Inline ActionsDoes you comment refers to the 'why not adhere' request ? Please see the expanded sentence with a reference to POSIX requirements for pthread_mutex_setprioceiling(3). kib: Does you comment refers to the 'why not adhere' request ? Please see the expanded sentence… | |||||
Done Inline ActionsSorry, not enough context I guess. After the lock is obtained the new ceiling value emaste: Sorry, not enough context I guess.
After the lock is obtained **the** new ceiling value | |||||
The arguments to the request are: | |||||
.Bl -tag -width "It Fa uaddr2" | |||||
.It Fa obj | |||||
Pointer to the | |||||
.Vt struct ucond . | |||||
.It Fa val | |||||
Request flags, see below. | |||||
.It Fa uaddr1 | |||||
Pointer to the umutex. | |||||
.It Fa uaddr2 | |||||
Optional pointer to the | |||||
emasteUnsubmitted Done Inline Actionspointer to a emaste: pointer to **a**
This one's debatable I think but **a** seems more natural to me.
(If no type… | |||||
.Vt struct timespec | |||||
for timeout specification. | |||||
.El | |||||
.Pp | |||||
The request must be issued by the thread owning the mutex pointed to | |||||
by the | |||||
.Fa uaddr1 | |||||
argument. | |||||
The | |||||
.Dv c_hash_waiters | |||||
member of the | |||||
.Vt struct ucond , | |||||
pointed to by the | |||||
.Fa obj | |||||
argument, is set to non-zero value, after which | |||||
emasteUnsubmitted Done Inline Actionsto a non-zero emaste: to **a** non-zero
or
to **an arbitrary* non-zero | |||||
.Fa uaddr1 | |||||
emasteUnsubmitted Done Inline Actionsthe uaddr1 emaste: **the** uaddr1 | |||||
mutex is unlocked (following appropriate protocol), and | |||||
emasteUnsubmitted Done Inline Actionsthe appropriate emaste: **the** appropriate | |||||
the current thread is put to sleep on the sleep queue keyed by | |||||
the | |||||
.Fa obj | |||||
argument. | |||||
The operations are performed atomically, i.e. it is guaranteed to not | |||||
emasteUnsubmitted Done Inline Actionsatomically. It emaste: atomically**. It**
| |||||
miss a wakeup from | |||||
.Dv UMTX_OP_CV_SIGNAL | |||||
or | |||||
.Dv UMTX_OP_CV_BROADCAST | |||||
sent between mutex unlock and putting the current thread on the sleep queue. | |||||
.Pp | |||||
Upon wakeup, if timed out and no other threads sleep in the same sleep | |||||
emasteUnsubmitted Done Inline Actionsif timeout occurred no other threads are sleeping emaste: if timeout occurred
if timeout expired
no other threads **are sleeping** | |||||
queue as ours, the | |||||
emasteUnsubmitted Done Inline Actionscan probably omit "as ours" emaste: can probably omit "as ours"
| |||||
.Dv c_hash_waiters | |||||
member is cleared. | |||||
After wakeup, the | |||||
.Fa uaddr1 | |||||
umutex is not relocked. | |||||
.Pp | |||||
The following flags are defined: | |||||
.Bl -tag -width "Dv CVWAIT_CLOCKID" | |||||
.It Dv CVWAIT_ABSTIME | |||||
Timeout is absolute. | |||||
.It Dv CVWAIT_CLOCKID | |||||
Clockid is provided. | |||||
Done Inline Actionsoops correction to my earlier comment. If the timeout expired emaste: oops correction to my earlier comment. If **the** timeout expired | |||||
.El | |||||
.Pp | |||||
Optionally, a timeout for the request may be specified. | |||||
Unlike other requests, the timeout value is specified by naked | |||||
emasteUnsubmitted Done Inline Actionsnaked is probably unclear here. emaste: naked is probably unclear here.
maybe "specified **directly** by a struct timespec? | |||||
.Vt struct timespec , | |||||
pointed to by the | |||||
.Fa uaddr2 | |||||
argument. | |||||
If the | |||||
.Dv CVWAIT_CLOCKID | |||||
flag is provided, the timeout uses clock from the | |||||
emasteUnsubmitted Done Inline Actionsuses the clock emaste: uses **the** clock | |||||
.Dv c_clockid | |||||
member of the | |||||
.Vt struct ucond , | |||||
pointed to by | |||||
.Fa obj | |||||
argument. | |||||
Otherwise, | |||||
.Dv CLOCK_REALTIME | |||||
is used, regardless of the clock identifier possibly specified in the | |||||
.Vt struct _umtx_time . | |||||
If the | |||||
.Dv CVWAIT_ABSTIME | |||||
flag is supplied, timeout specifies absolute time value, otherwise | |||||
emasteUnsubmitted Done Inline Actionssupplied, the timeout emaste: supplied, **the** timeout | |||||
it denotes a relative time interval. | |||||
.Pp | |||||
The request is not restartable, an unblocked signal delivered during | |||||
emasteUnsubmitted Done Inline Actionsrestartable. An emaste: restartable**. An** | |||||
the wait always results in sleep interruption and | |||||
.Er EINTR | |||||
error. | |||||
.It Dv UMTX_OP_CV_SIGNAL | |||||
Wake up one condition waiter. | |||||
The arguments to the request are: | |||||
.Bl -tag -width "It Fa obj" | |||||
.It Fa obj | |||||
Pointer to | |||||
.Vt struct ucond . | |||||
.El | |||||
.Pp | |||||
The request wakes up at most one thread sleeping on the sleep queue keyed | |||||
by the | |||||
.Fa obj | |||||
argument. | |||||
If woken up thread was the last on the sleep queue, the | |||||
emasteUnsubmitted Done Inline ActionsIf the woken emaste: If **the** woken | |||||
.Dv c_has_waiters | |||||
member of the | |||||
.Vt struct ucond | |||||
is cleared. | |||||
.It Dv UMTX_OP_CV_BROADCAST | |||||
Wake up all condition waiters. | |||||
The arguments to the request are: | |||||
.Bl -tag -width "It Fa obj" | |||||
.It Fa obj | |||||
Pointer to | |||||
.Vt struct ucond . | |||||
.El | |||||
.Pp | |||||
The request wakes up all threads sleeping on the sleep queue keyed by the | |||||
.Fa obj | |||||
argument. | |||||
The | |||||
.Dv c_has_waiters | |||||
member of the | |||||
.Vt struct ucond | |||||
is cleared. | |||||
.It Dv UMTX_OP_WAIT_UINT | |||||
Same as | |||||
.Dv UMTX_OP_WAIT , | |||||
but the type of the variable pointed to by | |||||
.Fa obj | |||||
is | |||||
.Vt u_int , | |||||
i.e. 32-bit integer. | |||||
.It Dv UMTX_OP_RW_RDLOCK | |||||
Read-lock a | |||||
.Vt struct rwlock | |||||
lock. | |||||
The arguments to the request are: | |||||
.Bl -tag -width "It Fa obj" | |||||
.It Fa obj | |||||
Pointer to the lock (of type | |||||
.Vt struct rwlock ) | |||||
to be read-locked. | |||||
.It Fa val | |||||
Additional flags to augment locking behaviour. | |||||
The valid flags in the | |||||
.Fa val | |||||
argument are: | |||||
.Bl -tag -width "It Dv URWLOCK_PREFER_READER" | |||||
.It Dv URWLOCK_PREFER_READER | |||||
.El | |||||
.El | |||||
.Pp | |||||
The request obtains the read lock on the specified | |||||
.Vt struct rwlock , | |||||
emasteUnsubmitted Done Inline Actionsomit , emaste: omit , | |||||
by incrementing the counter of readers in the | |||||
emasteUnsubmitted Done Inline Actionsthe count of readers perhaps? emaste: the **count** of readers perhaps? | |||||
.Dv rw_state | |||||
word of the structure. | |||||
If the | |||||
.Dv URWLOCK_WRITE_OWNER | |||||
bit is set in the word | |||||
.Dv rw_state , | |||||
the lock was granted to a writer which not yet relinguished its ownership, | |||||
emasteUnsubmitted Done Inline Actionswhich has not yet ... ownership. In this case... emaste: which **has** not yet ... ownership**. In this** case... | |||||
in which case the current thread is put to sleep until it makes sense to | |||||
retry. | |||||
.Pp | |||||
If the | |||||
.Dv URWLOCK_PREFER_READER | |||||
flag is set either in the | |||||
.Dv rw_flags | |||||
word of the structure, or in the | |||||
.Fa val | |||||
argument of the request, presence of the threads trying to obtain | |||||
emasteUnsubmitted Done Inline Actionsthe presence of threads emaste: **the** presence of threads | |||||
the write lock on the same structure does not prevent the current thread | |||||
to try to obtain the read lock. | |||||
emasteUnsubmitted Done Inline Actionsfrom trying to obtain emaste: **from trying** to obtain | |||||
Otherwise, if the flag is not set, and the | |||||
.Dv URWLOCK_WRITE_WAITERS | |||||
flag is set in | |||||
.Dv rw_state , | |||||
current thread does not attempt to obtain read-lock, instead it sets the | |||||
emasteUnsubmitted Done Inline Actionsthe current thread ... read-lock. Instead it sets emaste: **the** current thread ... read-lock**. Instead** it sets | |||||
.Dv URWLOCK_READ_WAITERS | |||||
in the | |||||
.Dv rw_state | |||||
word and puts itself to sleep on corresponding sleep queue. | |||||
Upon wakeup, the locking conditions are re-evaluated. | |||||
.Pp | |||||
Optionally, a timeout for the request may be specified. | |||||
.Pp | |||||
The request is not restartable, an unblocked signal delivered during | |||||
emasteUnsubmitted Done Inline Actionsrestartable. An unblocked emaste: restartable**. An** unblocked | |||||
the wait always results in sleep interruption and | |||||
.Er EINTR | |||||
error. | |||||
.It Dv UMTX_OP_RW_WRLOCK | |||||
Write-lock a | |||||
.Vt struct rwlock | |||||
lock. | |||||
The arguments to the request are: | |||||
.Bl -tag -width "It Fa obj" | |||||
.It Fa obj | |||||
Pointer to the lock (of type | |||||
.Vt struct rwlock ) | |||||
to be write-locked. | |||||
.El | |||||
.Pp | |||||
The request obtain the write lock on the specified | |||||
.Vt struct rwlock , | |||||
by setting the | |||||
.Dv URWLOCK_WRITE_OWNER | |||||
bit in the | |||||
.Dv rw_state | |||||
word of the structure. | |||||
If there is already a write lock owner, as indicated by the already set | |||||
.Dv URWLOCK_WRITE_OWNER | |||||
bit, or there are already read lock owners, as indicated by the read-lock | |||||
counter, the current thread does not attempt to obtain write-lock, | |||||
instead it sets the | |||||
.Dv URWLOCK_WRITE_WAITERS | |||||
in the | |||||
.Dv rw_state | |||||
word and puts itself to sleep on corresponding sleep queue. | |||||
Upon wakeup, the locking conditions are re-evaluated. | |||||
Done Inline Actionsrequest obtains a write lock on the specified emaste: request **obtains a** write lock on the specified
(It's hard for me to explain article choice… | |||||
.Pp | |||||
Optionally, a timeout for the request may be specified. | |||||
.Pp | |||||
The request is not restartable, an unblocked signal delivered during | |||||
the wait always results in sleep interruption and | |||||
.Er EINTR | |||||
error. | |||||
Done Inline Actionsindicated by the URWLOCK_WRITE_OWNER bit being set, emaste: indicated by the URWLOCK_WRITE_OWNER bit being set, | |||||
.It Dv UMTX_OP_RW_UNLOCK | |||||
Unlock rwlock. | |||||
Done Inline Actionsstrip this "already": there are read lock owners already makes sense in the case of a write lock owner, since we're trying to get the write lock ourselves emaste: strip this "already": there are read lock owners
already makes sense in the case of a write… | |||||
The arguments to the request are: | |||||
Done Inline Actionsobtain the write-lock. Instead (I'm puzzling over article choice here because I think it should be a at line 810. It makes sense to me because the "struct rwlock" above suggests "a lock".) emaste: obtain **the** write-lock**.**
**Instead**
(I'm puzzling over article choice here because I… | |||||
.Bl -tag -width "It Fa obj" | |||||
.It Fa obj | |||||
Pointer to the lock (of type | |||||
.Vt struct rwlock ) | |||||
to be unlocked. | |||||
.El | |||||
.Pp | |||||
Type of the unlock (read or write) is determined by the | |||||
current lock state. | |||||
Note that the | |||||
.Vt struct rwlock | |||||
does not save information about thread identity which | |||||
acquired the lock. | |||||
.Pp | |||||
If there are pending writers after the unlock, and the | |||||
.Dv URWLOCK_PREFER_READER | |||||
flag is not set in the | |||||
.Dv rw_flags | |||||
member of the | |||||
.Fa *obj | |||||
structure, one writer is woken up. | |||||
If the | |||||
.Dv URWLOCK_PREFER_READER | |||||
flag is set, a pending writer is woken up only if there is | |||||
no pending readers. | |||||
Done Inline ActionsThe unlock type (read or write) emaste: **The unlock type** (read or write) | |||||
.Pp | |||||
If there are no pending writers, or, for the case when | |||||
.Dv URWLOCK_PREFER_READER | |||||
flag is set, then all pending readers are woken up by unlock. | |||||
Done Inline Actionsabout the identity of the thread emaste: about **the identity of the thread** | |||||
.It Dv UMTX_OP_WAIT_UINT_PRIVATE | |||||
Same as | |||||
.Dv UMTX_OP_WAIT_UINT , | |||||
but unconditionally select process-private sleep queue. | |||||
.It Dv UMTX_OP_WAKE_PRIVATE | |||||
Same as | |||||
.Dv UMTX_OP_WAKE , | |||||
but unconditionally select process-private sleep queue. | |||||
.It Dv UMTX_OP_MUTEX_WAIT | |||||
Not Done Inline ActionsHow is the one chosen? emaste: How is the one chosen? | |||||
Not Done Inline ActionsIt is explained in the last paragraph of the SLEEP QUEUES subsection. I do not see it useful to repeat the formulation several times, it was the reason for the subsection writing. kib: It is explained in the last paragraph of the SLEEP QUEUES subsection. I do not see it useful… | |||||
Done Inline ActionsYeah, definitely not useful to repeat it again. emaste: Yeah, definitely not useful to repeat it again.
Do you think it's valuable to write something… | |||||
Wait for the mutex availability. | |||||
The arguments to the request are: | |||||
.Bl -tag -width "It Fa obj" | |||||
.It Fa obj | |||||
Address of the mutex. | |||||
.El | |||||
Done Inline Actionsor, in the case that the URWLOCK_PREFER_READER flag... emaste: or, **in** the case **that** the URWLOCK_PREFER_READER flag... | |||||
.Pp | |||||
Similarly to the | |||||
.Dv UMTX_OP_MUTEX_LOCK , | |||||
put the requesting thread to sleep if the mutex lock cannot be obtained | |||||
immediately. | |||||
The | |||||
Done Inline Actionsthe process-private emaste: **the** process-private | |||||
.Dv UMUTEX_CONTESTED | |||||
bit is set in the | |||||
.Dv m_owner | |||||
word of the mutex to indicate waiter, before the thread is added to | |||||
Done Inline Actionsthe process-pirvate emaste: **the** process-pirvate | |||||
the sleep queue. | |||||
Unlike the | |||||
.Dv UMTX_OP_MUTEX_LOCK | |||||
request, the lock is not obtained. | |||||
.Pp | |||||
The operation is not implemented for priority protected and | |||||
priority inherited protocol mutexes. | |||||
.Pp | |||||
Optionally, a timeout for the request may be specified. | |||||
.Pp | |||||
.Pp | |||||
The request with a timeout specified is not restartable, an unblocked | |||||
signal delivered during the wait always results in sleep interruption and | |||||
.Er EINTR | |||||
error. | |||||
The request without a timeout automatically restarts if the signal disposition | |||||
requested restart via the | |||||
Done Inline ActionsMaybe: emaste: Maybe:
indicate that there is a waiter | |||||
.Dv SA_RESTART | |||||
flag in | |||||
.Vt struct sigaction | |||||
member | |||||
.Dv sa_flags . | |||||
.It Dv UMTX_OP_NWAKE_PRIVATE | |||||
Wake up the batch of sleeping thread. | |||||
The arguments to the request are: | |||||
.Bl -tag -width "It Fa obj" | |||||
.It Fa obj | |||||
Pointer to the array of pointers. | |||||
.It Fa val | |||||
Number of elements in the array pointed to by | |||||
.Fa obj . | |||||
.El | |||||
.Pp | |||||
For each element in the array pointed to by | |||||
.Fa obj , | |||||
wakes up all threads waiting on the | |||||
.Em private | |||||
sleep queue with the key | |||||
being the byte addressed by the array element. | |||||
.It Dv UMTX_OP_MUTEX_WAKE | |||||
Check if the normal umutex is unlocked and wake up a waiter. | |||||
The arguments for the request are: | |||||
Done Inline ActionsWake up multiple sleeping threads emaste: Wake up multiple sleeping threads
or
Wake up a batch of sleeping threads | |||||
.Bl -tag -width "It Fa obj" | |||||
.It Fa obj | |||||
Pointer to the umutex. | |||||
.El | |||||
.Pp | |||||
If the | |||||
.Dv m_owner | |||||
word of the mutex pointed to by the | |||||
.Fa obj | |||||
argument indicates unowned mutex, which has its contention indicator bit | |||||
.Dv UMUTEX_CONTESTED | |||||
set, clear the bit and wake up one waiter in the sleep queue associated | |||||
with the byte addressed by the | |||||
.Fa obj , | |||||
if any. | |||||
Only normal mutexes are supported by the request, i.e. the sleep | |||||
queue, where the waiter to wake up is chosen, is always a sleep queue | |||||
for normal mutex type. | |||||
.It Dv UMTX_OP_MUTEX_WAKE2 | |||||
Check if the umutex is unlocked and wake up a waiter. | |||||
The arguments for the request are: | |||||
.Bl -tag -width "It Fa obj" | |||||
.It Fa obj | |||||
Pointer to the umutex. | |||||
.It Fa val | |||||
The umutex flags. | |||||
.El | |||||
.Pp | |||||
The request does not read the | |||||
.Dv m_flags | |||||
member of the | |||||
.Vt struct umutex , | |||||
instead, the | |||||
.Fa val | |||||
argument supplies flag information, in particular, to determine the | |||||
sleep queue where the waiters are found for wake up. | |||||
Done Inline ActionsI think the "where the waiter" is implicit and makes it harder for me to follow. Perhaps: Only normal mutexes are supported by the request. emaste: I think the "where the waiter" is implicit and makes it harder for me to follow. Perhaps:
Only… | |||||
.Pp | |||||
If the mutex is unowned, one waiter is woken up. | |||||
.Pp | |||||
If the mutex memory cannot be accessed, all waiters are woken up. | |||||
.Pp | |||||
If there are more than one waiter on the sleep queue, or there is only | |||||
one waiter but the mutex is owned by a thread, the | |||||
.Dv UMUTEX_CONTESTED | |||||
bit is set in the | |||||
.Dv m_owner | |||||
word of the | |||||
.Vt struct umutex | |||||
the request operates upon. | |||||
.It Dv UMTX_OP_SEM2_WAIT | |||||
Wait until semaphore is available. | |||||
The arguments to the request are: | |||||
.Bl -tag -width "It Fa obj" | |||||
.It Fa obj | |||||
Pointer to the semaphore (of type | |||||
.Vt struct _usem2 ) . | |||||
.El | |||||
Put the requesting thread onto a sleep queue if the semaphore counter | |||||
is zero. | |||||
If thread is put to sleep, the | |||||
Done Inline Actionsis more than one emaste: **is** more than one | |||||
.Dv USEM_HAS_WAITERS | |||||
bit is set in the | |||||
.Dv _count | |||||
word to indicate waiters. | |||||
Function returns either due to | |||||
.Dv _count | |||||
indicating the semaphore is available (non-zero count due to post), | |||||
or due to a wakeup. | |||||
The return does not guarantee that the semaphore is available, | |||||
nor does it consume the semaphore lock on successfull return. | |||||
.Pp | |||||
Optionally, a timeout for the request may be specified. | |||||
.Pp | |||||
The request with non-absolute timeout value is not restartable, | |||||
an unblocked signal delivered during such wait results in sleep | |||||
interruption and | |||||
.Er EINTR | |||||
error. | |||||
.It Dv UMTX_OP_SEM2_WAKE | |||||
Wake up waiters on the semaphore lock. | |||||
The arguments to the request are: | |||||
.Bl -tag -width "It Fa obj" | |||||
.It Fa obj | |||||
Pointer to the semaphore (of type | |||||
.Vt struct _usem2 ) . | |||||
.El | |||||
.Pp | |||||
The request wakes up one waiter for the semaphore lock. | |||||
Done Inline Actionsonly one l, successful emaste: only one l, successful | |||||
The function does not increment the semaphore lock count. | |||||
If the | |||||
.Dv USEM_HAS_WAITERS | |||||
bit was set in the | |||||
Done Inline ActionsA request ... not restartable. An unblocked emaste: **A** request ... not restartable**.**
**An** unblocked | |||||
.Dv _count | |||||
word, and the last sleeing thread was woken up, the bit is cleared. | |||||
.It Dv UMTX_OP_SHM | |||||
Manage the anonymous POSIX shared objects (see | |||||
.Xr shm_open 2 ) , | |||||
which can be attached to a byte of physical memory, mapped into the | |||||
process address space. | |||||
The objects are used to implement process-shared locks in | |||||
.Dv libthr . | |||||
.Pp | |||||
The | |||||
.Fa val | |||||
argument specifies sub-request of the | |||||
.Dv UMTX_OP_SHM | |||||
request: | |||||
.Bl -tag -width "Dv UMTX_SHM_DESTROY" | |||||
.It Dv UMTX_SHM_CREAT | |||||
Creates the POSIX anonymous memory shared object, which can be looked up | |||||
with the specified key | |||||
.Fa uaddr. | |||||
Done Inline Actionssleeping emaste: slee**p**ing | |||||
If the object associated with the | |||||
.Fa uaddr | |||||
key already exists, it is returned instead of creating new object. | |||||
The object' size is one page. | |||||
On success, the file descriptor referencing the object is returned. | |||||
The descriptor can be used for mapping the object using | |||||
.Xr mmap 2 , | |||||
or for other shared memory operations. | |||||
.It Dv UMTX_SHM_LOOKUP | |||||
Same as | |||||
.Dv UMTX_SHM_CREATE | |||||
Done Inline Actionsspecifies the sub-request emaste: specifies **the** sub-request | |||||
request, but if there is no shared memory object associated with | |||||
the specified key | |||||
.Fa uaddr , | |||||
an error is returned, and new object is not created. | |||||
.It Dv UMTX_SHM_DESTROY | |||||
De-associate the shared object with the specified key | |||||
.Fa uaddr. | |||||
The object is destroyed after the last open file descriptor and the | |||||
last mapping for it are destroyed. | |||||
.It Dv UMTX_SHM_ALIVE | |||||
Done Inline Actionscreating a new object emaste: creating **a** new object | |||||
Checks whether there is an alive shared object associated with the | |||||
Done Inline Actionsobject's size emaste: object's size | |||||
supplied key | |||||
.Fa uaddr . | |||||
Returns zero if there is, and an error otherwise. | |||||
This request is an optimization of the | |||||
.Dv UMTX_SHM_LOOKUP | |||||
request. | |||||
It is cheaper when only liveness of the associated object is asked | |||||
for, since file descriptor is not installed in the process fd table | |||||
on success. | |||||
.El | |||||
.Pp | |||||
The | |||||
.Fa uaddr | |||||
argument specifies the virtual address, which backing physical memory | |||||
byte identity is used as a key for the anonymous shared object | |||||
creation or lookup. | |||||
Done Inline Actionsthe last open file descriptor is closed and the last mapping for it is destroyed ? emaste: the last open file descriptor is closed and the last mapping for it is destroyed ?
| |||||
.El | |||||
.Sh RETURN VALUES | |||||
Done Inline ActionsMaybe is a live shared object? I think "an alive shared object" is acceptable but unconventional English. emaste: Maybe is **a live** shared object? I think "an alive shared object" is acceptable but… | |||||
If successful, | |||||
all requests, except | |||||
.Dv UMTX_SHM_CREAT | |||||
and | |||||
.Dv UMTX_SHM_LOOKUP | |||||
sub-requests of the | |||||
.Dv UMTX_OP_SHM | |||||
Done Inline Actionswhen only the liveness ... since the file descriptor emaste: when only **the** liveness ... since **the** file descriptor | |||||
request, will return zero. | |||||
The | |||||
.Dv UMTX_SHM_CREAT | |||||
and | |||||
.Dv UMTX_SHM_LOOKUP | |||||
return POSIX shared memory file descriptor on success. | |||||
On error \-1 is returned, and | |||||
.Va errno | |||||
variable is set to indicate the error. | |||||
.Sh ERRORS | |||||
The | |||||
.Fn _umtx_op | |||||
operations will return the following errors: | |||||
.Bl -tag -width Er | |||||
.It Bq Er EFAULT | |||||
One of the arguments point to the invalid memory. | |||||
.It Bq Er EINVAL | |||||
The clock identifier, specified for the | |||||
.Vt struct _umtx_time | |||||
timeout parameter, or in | |||||
.Dv c_clockid | |||||
member of | |||||
.Vt struct ucond, | |||||
is invalid. | |||||
Not Done Inline Actionsreturn a POSIX emaste: return **a** POSIX | |||||
.It Bq Er EINVAL | |||||
The type of the mutex, encoded by the | |||||
Done Inline Actionsthe errno variable (or just "and errno is set") emaste: **the** errno variable
(or just "and errno is set") | |||||
.Dv m_flags | |||||
member of | |||||
.Vt struct umutex , | |||||
is invalid. | |||||
.It Bq Er EINVAL | |||||
The | |||||
.Dv m_owner | |||||
member of the | |||||
Done Inline Actionspoints to invalid memory emaste: point**s** to invalid memory | |||||
.Vt struct umutex | |||||
has changed the thread identifier of lock owner during unlock. | |||||
.It Bq Er EINVAL | |||||
The | |||||
.Dv timeout.tv_sec | |||||
Done Inline Actionsin the c_clockid emaste: in **the** c_clockid | |||||
or | |||||
.Dv timeout.tv_nsec | |||||
members of | |||||
.Vt struct _umtx_time | |||||
is less than zero, or | |||||
.Dv timeout.tv_nsec | |||||
member is greater than specified 1000000000. | |||||
.It Bq Er EINVAL | |||||
The | |||||
.Fa op | |||||
argument specifies invalid operation. | |||||
.It Bq Er EINVAL | |||||
The | |||||
.Fa uaddr1 | |||||
argument for the | |||||
Done Inline Actionshas changed the lock owner thread identifier during unlock. emaste: has changed the lock owner thread identifier during unlock.
| |||||
.Dv UMTX_OP_SHM | |||||
request specifies invalid operation. | |||||
.It Bq Er EINVAL | |||||
The | |||||
.Dv UMTX_OP_SET_CEILING | |||||
request specifies non priority protected mutex. | |||||
Done Inline Actionsmember of emaste: member of | |||||
.It Bq Er EINVAL | |||||
The new ceiling value for the | |||||
.Dv UMTX_OP_SET_CEILING , | |||||
or the values read from | |||||
Done Inline Actionseither "or the timeout.tv_nsec member..." emaste: either "or **the** timeout.tv_nsec member..."
or just "or timeout.tv_nsec is greater" (no need… | |||||
.Dv m_ceilings | |||||
array during lock or unlock operations, are greater than | |||||
.Dv RTP_PRIO_MAX . | |||||
.It Bq Er EPERM | |||||
Unlock attempted on the object which lock is not owned by the | |||||
current thread. | |||||
.It Bq Er ENOTTY | |||||
The shared memory object, associated with the address, passed to the | |||||
.Dv UMTX_SHM_ALIVE | |||||
sub-request of | |||||
.Dv UMTX_OP_SHM | |||||
request, was destroyed. | |||||
.It Bq Er ESRCH | |||||
For the | |||||
.Dv UMTX_SHM_LOOKUP , | |||||
.Dv UMTX_SHM_DESTROY , | |||||
and | |||||
.Dv UMTX_SHM_ALIVE | |||||
Done Inline Actionsmaybe "one of the values read from" or "one or more of the values read from" emaste: maybe "one of the values read from" or "one or more of the values read from" | |||||
sub-requests of the | |||||
Done Inline Actionsthe m_ceilings emaste: **the** m_ceilings | |||||
.Dv UMTX_OP_SHM | |||||
Done Inline Actionsis greater than emaste: **is** greater than | |||||
request, there is no shared object associated with the provided key. | |||||
.It Bq Er EAGAIN | |||||
Maximum allowed number of readers | |||||
Done Inline ActionsUnlock attempted on an object not owned by the current thread emaste: Unlock attempted on an object not owned by the current thread
(or "owned by another thread", as… | |||||
Not Done Inline ActionsIt may be not owned by any thread, for this error, as well. kib: It may be not owned by any thread, for this error, as well. | |||||
.Dv ( URWLOCK_MAX_READERS ) | |||||
were already granted the ownership of the given | |||||
.Vt struct rwlock | |||||
Done Inline Actionsno , after address emaste: no , after address | |||||
for read. | |||||
.It Bq Er EBUSY | |||||
A try mutex lock operation was not able to obtain the lock. | |||||
.It Bq Er ETIMEDOUT | |||||
The request specified timeout in | |||||
.Fa uaddr1 | |||||
and | |||||
.Fa uaddr2 | |||||
arguments and timed out before obtaining the lock or being woken up. | |||||
.It Bq Er EINTR | |||||
A signal was delivered during wait, for non-restartable operation. | |||||
Operations with timeouts are typically non-restartable, but timeouts | |||||
specified in absolute time may be restartable. | |||||
.It Bq Er ERESTART | |||||
A signal was delivered during wait, for restartable operation. | |||||
Done Inline ActionsThe maximum number of emaste: **The** maximum **number** of | |||||
Mutex lock requests without timeout specified are restartable. | |||||
.El | |||||
Done Inline Actionsgranted ownership of (no the) emaste: granted ownership of (no the) | |||||
.Sh SEE ALSO | |||||
.Xr clock_gettime 2 , | |||||
.Xr mmap 2 , | |||||
.Xr shm_open 2 , | |||||
.Xr sigaction 2 , | |||||
.Xr thr_exit 2 , | |||||
Done Inline Actionsspecified a timeout in the uaddr1 or uaddr2 argument, and timed out... (assuming "or" instead of "and" is desired) emaste: specified **a** timeout in **the** uaddr1 **or** uaddr2 argument, and timed out...
(assuming… | |||||
Not Done Inline ActionsBoth uaddr1 and uaddr2 are needed to specify the timeout, uaddr1 is size, uaddr2 is the pointer to a structure sized by uaddr1. This was explained in 'structures'. kib: Both uaddr1 and uaddr2 are needed to specify the timeout, uaddr1 is size, uaddr2 is the pointer… | |||||
.Xr thr_kill 2 , | |||||
.Xr thr_kill2 2 , | |||||
.Xr thr_new 2 , | |||||
.Xr thr_self 2 , | |||||
.Xr thr_set_name 2 , | |||||
.Xr signal 3 | |||||
Done Inline Actionsfor a non-restartable emaste: for **a** non-restartable | |||||
.Sh STANDARDS | |||||
The | |||||
.Fn _umtx_op | |||||
Done Inline Actionsa timeout in the uaddr1 and uaddr2 arguments, and timed emaste: a timeout in **the** uaddr1 and uaddr2 arguments, and timed | |||||
system call is non-standard and is used by the | |||||
Done Inline Actionsfor a restartable emaste: for **a** restartable | |||||
.Lb libthr | |||||
Done Inline Actionswithout a timeout emaste: without **a** timeout | |||||
to implement | |||||
.St -p1003.1-2001 | |||||
.Xr pthread(3) | |||||
functionality. |
I would drop the 'the' and second comma (before which are)