diff options
Diffstat (limited to 'lib/libc/sys/_umtx_op.2')
-rw-r--r-- | lib/libc/sys/_umtx_op.2 | 1531 |
1 files changed, 0 insertions, 1531 deletions
diff --git a/lib/libc/sys/_umtx_op.2 b/lib/libc/sys/_umtx_op.2 deleted file mode 100644 index ecd46b7d0247..000000000000 --- a/lib/libc/sys/_umtx_op.2 +++ /dev/null @@ -1,1531 +0,0 @@ -.\" 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 November 23, 2020 -.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. -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 indent -.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 -See the -.Sx SLEEP QUEUES -subsection below for more details on sleep queues. -.El -.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]; - uintptr_t m_rb_lnk; -}; -.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 indent -.It Dv UMUTEX_UNOWNED -Zero, the value stored in the unowned lock. -.It Dv UMUTEX_CONTESTED -The contention indicator. -.It Dv UMUTEX_RB_OWNERDEAD -A thread owning the robust mutex terminated. -The mutex is in unlocked state. -.It Dv UMUTEX_RB_NOTRECOV -The robust mutex is in a non-recoverable state. -It cannot be locked until reinitialized. -.El -.Pp -The -.Dv m_flags -field may contain the following umutex-specific flags, in addition to -the common flags: -.Bl -tag -width indent -.It Dv UMUTEX_PRIO_INHERIT -Mutex implements -.Em Priority Inheritance -protocol. -.It Dv UMUTEX_PRIO_PROTECT -Mutex implements -.Em Priority Protection -protocol. -.It Dv UMUTEX_ROBUST -Mutex is robust, as described in the -.Sx ROBUST UMUTEXES -section below. -.It Dv UMUTEX_NONCONSISTENT -Robust mutex is in a transient non-consistent state. -Not used by kernel. -.El -.Pp -In the manual page, mutexes not having -.Dv UMUTEX_PRIO_INHERIT -and -.Dv UMUTEX_PRIO_PROTECT -flags set, are called normal mutexes. -Each type of mutex -.Pq normal, priority-inherited, and priority-protected -has a separate sleep queue associated -with the given key. -.Pp -For priority protected mutexes, the -.Dv m_ceilings -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. -In this case, -.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, -.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 { - 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 -request. -.Pp -The -.Dv c_flags -field contains flags. -Only the common flags -.Pq 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. -Valid clock identifiers are a subset of those for -.Xr clock_gettime 2 : -.Bl -bullet -compact -.It -.Dv CLOCK_MONOTONIC -.It -.Dv CLOCK_MONOTONIC_FAST -.It -.Dv CLOCK_MONOTONIC_PRECISE -.It -.Dv CLOCK_PROF -.It -.Dv CLOCK_REALTIME -.It -.Dv CLOCK_REALTIME_FAST -.It -.Dv CLOCK_REALTIME_PRECISE -.It -.Dv CLOCK_SECOND -.It -.Dv CLOCK_UPTIME -.It -.Dv CLOCK_UPTIME_FAST -.It -.Dv CLOCK_UPTIME_PRECISE -.It -.Dv CLOCK_VIRTUAL -.El -.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 indent -.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 -.Vt struct rwlock , -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 indent -.It Dv URWLOCK_PREFER_READER -If specified, immediately grant read lock requests when -.Dv urwlock -is already read-locked, even in presence of 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 -.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 -.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, which is 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 indent -.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 -.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 -.Dv _flags -argument allows the following flags to further define the timeout behaviour: -.Bl -tag -width indent -.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 -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 -When a locking request cannot be immediately satisfied, the thread is -typically put to -.Em sleep , -which is a non-runnable state terminated by the -.Em wake -operation. -Lock operations include a -.Em try -variant which returns an error rather than sleeping if the lock cannot -be obtained. -Also, -.Fn _umtx_op -provides requests which explicitly 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 . -A sleep queue is identified by a key, which for -.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. -This mechanism enables the construction of -.Em process-shared -locks. -.Pp -A related attribute of the key is shareability. -Some requests always interpret keys as private for the current process, -creating sleep queues with the scope of the current process even if -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 the lock scope to be limited -regardless of the kind of backing memory. -.Pp -Only the address of the start byte of the variable specified as key is -important for determining corresponding sleep queue. -The size of the variable does not matter, so, for example, sleep on the same -address interpeted as -.Vt uint32_t -and -.Vt long -on a little-endian 64-bit platform would collide. -.Pp -The last attribute of the key is the object type. -The sleep queue to which a sleeping thread is assigned is an individual -one for simple wait requests, mutexes, rwlocks, condvars and other -primitives, even when the physical address of the key is same. -.Pp -When waking up a limited number of threads from a given sleep queue, -the highest priority threads that have been blocked for the longest on -the queue are selected. -.Ss ROBUST UMUTEXES -The -.Em robust umutexes -are provided as a substrate for a userspace library to implement -.Tn POSIX -robust mutexes. -A robust umutex must have the -.Dv UMUTEX_ROBUST -flag set. -.Pp -On thread termination, the kernel walks two lists of mutexes. -The two lists head addresses must be provided by a prior call to -.Dv UMTX_OP_ROBUST_LISTS -request. -The lists are singly-linked. -The link to next element is provided by the -.Dv m_rb_lnk -member of the -.Vt struct umutex . -.Pp -Robust list processing is aborted if the kernel finds a mutex -with any of the following conditions: -.Bl -dash -offset indent -compact -.It -the -.Dv UMUTEX_ROBUST -flag is not set -.It -not owned by the current thread, except when the mutex is pointed to -by the -.Dv robust_inactive -member of the -.Vt struct umtx_robust_lists_params , -registered for the current thread -.It -the combination of mutex flags is invalid -.It -read of the umutex memory faults -.It -the list length limit described in -.Xr libthr 3 -is reached. -.El -.Pp -Every mutex in both lists is unlocked as if the -.Dv UMTX_OP_MUTEX_UNLOCK -request is performed on it, but instead of the -.Dv UMUTEX_UNOWNED -value, the -.Dv m_owner -field is written with the -.Dv UMUTEX_RB_OWNERDEAD -value. -When a mutex in the -.Dv UMUTEX_RB_OWNERDEAD -state is locked by kernel due to the -.Dv UMTX_OP_MUTEX_TRYLOCK -and -.Dv UMTX_OP_MUTEX_LOCK -requests, the lock is granted and -.Er EOWNERDEAD -error is returned. -.Pp -Also, the kernel handles the -.Dv UMUTEX_RB_NOTRECOV -value of -.Dv the m_owner -field specially, always returning the -.Er ENOTRECOVERABLE -error for lock attempts, without granting the lock. -.Ss OPERATIONS -The following operations, requested by the -.Fa op -argument to the function, are implemented: -.Bl -tag -width indent -.It Dv UMTX_OP_WAIT -Wait. -The arguments for the request are: -.Bl -tag -width "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, the requesting thread is put to interruptible sleep -until woken up or the optionally specified timeout expires. -.Pp -The comparison and sleep are atomic. -In other words, if another thread writes a new value to -.Dv *obj -and then issues -.Dv UMTX_OP_WAKE , -the request is guaranteed to not miss the wakeup, -which might otherwise happen between comparison 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. -In particular, it is the user's duty to ensure the lock acquire -and release memory semantics, if the -.Dv UMTX_OP_WAIT -and -.Dv UMTX_OP_WAKE -requests are used as a substrate for implementing a simple lock. -.Pp -The request is not restartable. -An unblocked signal delivered during the wait always results in sleep -interruption and -.Er EINTR -error. -.Pp -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: -.Bl -tag -width "obj" -.It Fa obj -Pointer to a variable, used as a key to find sleeping threads. -.It Fa val -Up to -.Fa val -threads are woken up by this request. -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 "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 "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 because another thread owns -the lock, the current thread is put to 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 -A request with a timeout specified is not restartable. -An unblocked signal delivered during the wait always results in sleep -interruption and -.Er EINTR -error. -A request without timeout specified is always restarted after return -from a signal handler. -.It Dv UMTX_OP_MUTEX_UNLOCK -Unlock umutex. -The arguments to the request are: -.Bl -tag -width "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 . -The write is done with a release barrier, to provide lock leave semantic. -.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 "uaddr" -.It Fa obj -Pointer to the umutex. -.It Fa val -New ceiling value. -.It Fa uaddr -Address of a variable of type -.Vt uint32_t . -If not -.Dv NULL -and the update was successful, the previous ceiling value is -written to the location pointed to by -.Fa uaddr . -.El -.Pp -The request locks the umutex pointed to by the -.Fa obj -parameter, waiting for the lock if not immediately available. -After the lock is obtained, the new ceiling value -.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, -to conform to the -.Tn POSIX -requirements for the -.Xr pthread_mutex_setprioceiling 3 -interface. -.It Dv UMTX_OP_CV_WAIT -Wait for a condition. -The arguments to the request are: -.Bl -tag -width "uaddr2" -.It Fa obj -Pointer to the -.Vt struct ucond . -.It Fa val -Request flags, see below. -.It Fa uaddr -Pointer to the umutex. -.It Fa uaddr2 -Optional pointer to a -.Vt struct timespec -for timeout specification. -.El -.Pp -The request must be issued by the thread owning the mutex pointed to -by the -.Fa uaddr -argument. -The -.Dv c_hash_waiters -member of the -.Vt struct ucond , -pointed to by the -.Fa obj -argument, is set to an arbitrary non-zero value, after which the -.Fa uaddr -mutex is unlocked (following the appropriate protocol), and -the current thread is put to sleep on the sleep queue keyed by -the -.Fa obj -argument. -The operations are performed atomically. -It is guaranteed to not 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 the timeout expired and no other threads are sleeping in -the same sleep queue, the -.Dv c_hash_waiters -member is cleared. -After wakeup, the -.Fa uaddr -umutex is not relocked. -.Pp -The following flags are defined: -.Bl -tag -width "CVWAIT_CLOCKID" -.It Dv CVWAIT_ABSTIME -Timeout is absolute. -.It Dv CVWAIT_CLOCKID -Clockid is provided. -.El -.Pp -Optionally, a timeout for the request may be specified. -Unlike other requests, the timeout value is specified directly by a -.Vt struct timespec , -pointed to by the -.Fa uaddr2 -argument. -If the -.Dv CVWAIT_CLOCKID -flag is provided, the timeout uses the clock from the -.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, the timeout specifies absolute time value, otherwise -it denotes a relative time interval. -.Pp -The request is not restartable. -An unblocked signal delivered during -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 "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 the woken up thread was the last on the sleep queue, the -.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 "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 -.Pq a 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 "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 indent -.It Dv URWLOCK_PREFER_READER -.El -.El -.Pp -The request obtains the read lock on the specified -.Vt struct rwlock -by incrementing the count of readers in the -.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 has not yet relinquished -its ownership. -In this 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, the presence of the threads trying to obtain -the write lock on the same structure does not prevent the current thread -from trying to obtain the read lock. -Otherwise, if the flag is not set, and the -.Dv URWLOCK_WRITE_WAITERS -flag is set in -.Dv rw_state , -the current thread does not attempt to obtain read-lock. -Instead it sets the -.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 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 "obj" -.It Fa obj -Pointer to the lock (of type -.Vt struct rwlock ) -to be write-locked. -.El -.Pp -The request obtains a 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 -.Dv URWLOCK_WRITE_OWNER -bit being set, or there are read lock owners, as indicated -by the read-lock counter, the current thread does not attempt to -obtain the 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. -.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. -.It Dv UMTX_OP_RW_UNLOCK -Unlock rwlock. -The arguments to the request are: -.Bl -tag -width "obj" -.It Fa obj -Pointer to the lock (of type -.Vt struct rwlock ) -to be unlocked. -.El -.Pp -The unlock type (read or write) is determined by the -current lock state. -Note that the -.Vt struct rwlock -does not save information about the identity of the thread 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, selected as described in the -.Sx SLEEP QUEUES -subsection. -If the -.Dv URWLOCK_PREFER_READER -flag is set, a pending writer is woken up only if there is -no pending readers. -.Pp -If there are no pending writers, or, in the case that the -.Dv URWLOCK_PREFER_READER -flag is set, then all pending readers are woken up by unlock. -.It Dv UMTX_OP_WAIT_UINT_PRIVATE -Same as -.Dv UMTX_OP_WAIT_UINT , -but unconditionally select the process-private sleep queue. -.It Dv UMTX_OP_WAKE_PRIVATE -Same as -.Dv UMTX_OP_WAKE , -but unconditionally select the process-private sleep queue. -.It Dv UMTX_OP_MUTEX_WAIT -Wait for mutex availability. -The arguments to the request are: -.Bl -tag -width "obj" -.It Fa obj -Address of the mutex. -.El -.Pp -Similarly to the -.Dv UMTX_OP_MUTEX_LOCK , -put the requesting thread to sleep if the mutex lock cannot be obtained -immediately. -The -.Dv UMUTEX_CONTESTED -bit is set in the -.Dv m_owner -word of the mutex to indicate that there is a waiter, before the thread -is added to 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 -A request with a timeout specified is not restartable. -An unblocked signal delivered during the wait always results in sleep -interruption and -.Er EINTR -error. -A request without a timeout automatically restarts if the signal disposition -requested restart via the -.Dv SA_RESTART -flag in -.Vt struct sigaction -member -.Dv sa_flags . -.It Dv UMTX_OP_NWAKE_PRIVATE -Wake up a batch of sleeping threads. -The arguments to the request are: -.Bl -tag -width "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 a normal umutex is unlocked and wake up a waiter. -The arguments for the request are: -.Bl -tag -width "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. -The sleep queue is always one for a normal mutex type. -.Pp -This request is deprecated in favor of -.Dv UMTX_OP_MUTEX_WAKE2 -since mutexes using it cannot synchronize their own destruction. -That is, the -.Dv m_owner -word has already been set to -.Dv UMUTEX_UNOWNED -when this request is made, -so that another thread can lock, unlock and destroy the mutex -(if no other thread uses the mutex afterwards). -Clearing the -.Dv UMUTEX_CONTESTED -bit may then modify freed memory. -.It Dv UMTX_OP_MUTEX_WAKE2 -Check if a umutex is unlocked and wake up a waiter. -The arguments for the request are: -.Bl -tag -width "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. -.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 is 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 . -.It Dv UMTX_OP_SEM2_WAIT -Wait until semaphore is available. -The arguments to the request are: -.Bl -tag -width "obj" -.It Fa obj -Pointer to the semaphore (of type -.Vt struct _usem2 ) . -.It Fa uaddr -Size of the memory passed in via the -.Fa uaddr2 -argument. -.It Fa uaddr2 -Optional pointer to a structure of type -.Vt struct _umtx_time , -which may be followed by a structure of type -.Vt struct timespec . -.El -.Pp -Put the requesting thread onto a sleep queue if the semaphore counter -is zero. -If the thread is put to sleep, the -.Dv USEM_HAS_WAITERS -bit is set in the -.Dv _count -word to indicate waiters. -The 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 successful return. -.Pp -Optionally, a timeout for the request may be specified. -.Pp -A request with non-absolute timeout value is not restartable. -An unblocked signal delivered during such wait results in sleep -interruption and -.Er EINTR -error. -.Pp -If -.Dv UMTX_ABSTIME -was not set, and the operation was interrupted and the caller passed in a -.Fa uaddr2 -large enough to hold a -.Vt struct timespec -following the initial -.Vt struct _umtx_time , -then the -.Vt struct timespec -is updated to contain the unslept amount. -.It Dv UMTX_OP_SEM2_WAKE -Wake up waiters on semaphore lock. -The arguments to the request are: -.Bl -tag -width "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. -The function does not increment the semaphore lock count. -If the -.Dv USEM_HAS_WAITERS -bit was set in the -.Dv _count -word, and the last sleeping thread was woken up, the bit is cleared. -.It Dv UMTX_OP_SHM -Manage anonymous -.Tn POSIX -shared memory 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 the sub-request of the -.Dv UMTX_OP_SHM -request: -.Bl -tag -width indent -.It Dv UMTX_SHM_CREAT -Creates the anonymous shared memory object, which can be looked up -with the specified key -.Fa uaddr . -If the object associated with the -.Fa uaddr -key already exists, it is returned instead of creating a new object. -The object's 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 -request, but if there is no shared memory object associated with -the specified key -.Fa uaddr , -an error is returned, and no new object is 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 is closed -and the last mapping for it is destroyed. -.It Dv UMTX_SHM_ALIVE -Checks whether there is a live shared object associated with the -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 the liveness of the associated object is asked -for, since no file descriptor is 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. -.It Dv UMTX_OP_ROBUST_LISTS -Register the list heads for the current thread's robust mutex lists. -The arguments to the request are: -.Bl -tag -width "uaddr" -.It Fa val -Size of the structure passed in the -.Fa uaddr -argument. -.It Fa uaddr -Pointer to the structure of type -.Vt struct umtx_robust_lists_params . -.El -.Pp -The structure is defined as -.Bd -literal -struct umtx_robust_lists_params { - uintptr_t robust_list_offset; - uintptr_t robust_priv_list_offset; - uintptr_t robust_inact_offset; -}; -.Ed -.Pp -The -.Dv robust_list_offset -member contains address of the first element in the list of locked -robust shared mutexes. -The -.Dv robust_priv_list_offset -member contains address of the first element in the list of locked -robust private mutexes. -The private and shared robust locked lists are split to allow fast -termination of the shared list on fork, in the child. -.Pp -The -.Dv robust_inact_offset -contains a pointer to the mutex which might be locked in nearby future, -or might have been just unlocked. -It is typically set by the lock or unlock mutex implementation code -around the whole operation, since lists can be only changed race-free -when the thread owns the mutex. -The kernel inspects the -.Dv robust_inact_offset -in addition to walking the shared and private lists. -Also, the mutex pointed to by -.Dv robust_inact_offset -is handled more loosely at the thread termination time, -than other mutexes on the list. -That mutex is allowed to be not owned by the current thread, -in which case list processing is continued. -See -.Sx ROBUST UMUTEXES -subsection for details. -.El -.Pp -The -.Fa op -argument may be a bitwise OR of a single command from above with one or more of -the following flags: -.Bl -tag -width indent -.It Dv UMTX_OP__I386 -Request i386 ABI compatibility from the native -.Nm -system call. -Specifically, this implies that: -.Bl -hang -offset indent -.It -.Fa obj -arguments that point to a word, point to a 32-bit integer. -.It -The -.Dv UMTX_OP_NWAKE_PRIVATE -.Fa obj -argument is a pointer to an array of 32-bit pointers. -.It -The -.Dv m_rb_lnk -member of -.Vt struct umutex -is a 32-bit pointer. -.It -.Vt struct timespec -uses a 32-bit time_t. -.El -.Pp -.Dv UMTX_OP__32BIT -has no effect if this flag is set. -This flag is valid for all architectures, but it is ignored on i386. -.It Dv UMTX_OP__32BIT -Request non-i386, 32-bit ABI compatibility from the native -.Nm -system call. -Specifically, this implies that: -.Bl -hang -offset indent -.It -.Fa obj -arguments that point to a word, point to a 32-bit integer. -.It -The -.Dv UMTX_OP_NWAKE_PRIVATE -.Fa obj -argument is a pointer to an array of 32-bit pointers. -.It -The -.Dv m_rb_lnk -member of -.Vt struct umutex -is a 32-bit pointer. -.It -.Vt struct timespec -uses a 64-bit time_t. -.El -.Pp -This flag has no effect if -.Dv UMTX_OP__I386 -is set. -This flag is valid for all architectures. -.El -.Pp -Note that if any 32-bit ABI compatibility is being requested, then care must be -taken with robust lists. -A single thread may not mix 32-bit compatible robust lists with native -robust lists. -The first -.Dv UMTX_OP_ROBUST_LISTS -call in a given thread determines which ABI that thread will use for robust -lists going forward. -.Sh RETURN VALUES -If successful, -all requests, except -.Dv UMTX_SHM_CREAT -and -.Dv UMTX_SHM_LOOKUP -sub-requests of the -.Dv UMTX_OP_SHM -request, will return zero. -The -.Dv UMTX_SHM_CREAT -and -.Dv UMTX_SHM_LOOKUP -return a shared memory file descriptor on success. -On error \-1 is returned, and the -.Va errno -variable is set to indicate the error. -.Sh ERRORS -The -.Fn _umtx_op -operations can fail with the following errors: -.Bl -tag -width "[ETIMEDOUT]" -.It Bq Er EFAULT -One of the arguments point to invalid memory. -.It Bq Er EINVAL -The clock identifier, specified for the -.Vt struct _umtx_time -timeout parameter, or in the -.Dv c_clockid -member of -.Vt struct ucond, -is invalid. -.It Bq Er EINVAL -The type of the mutex, encoded by the -.Dv m_flags -member of -.Vt struct umutex , -is invalid. -.It Bq Er EINVAL -The -.Dv m_owner -member of the -.Vt struct umutex -has changed the lock owner thread identifier during unlock. -.It Bq Er EINVAL -The -.Dv timeout.tv_sec -or -.Dv timeout.tv_nsec -member of -.Vt struct _umtx_time -is less than zero, or -.Dv timeout.tv_nsec -is greater than 1000000000. -.It Bq Er EINVAL -The -.Fa op -argument specifies invalid operation. -.It Bq Er EINVAL -The -.Fa uaddr -argument for the -.Dv UMTX_OP_SHM -request specifies invalid operation. -.It Bq Er EINVAL -The -.Dv UMTX_OP_SET_CEILING -request specifies non priority protected mutex. -.It Bq Er EINVAL -The new ceiling value for the -.Dv UMTX_OP_SET_CEILING -request, or one or more of the values read from the -.Dv m_ceilings -array during lock or unlock operations, is greater than -.Dv RTP_PRIO_MAX . -.It Bq Er EPERM -Unlock attempted on an object not owned by the current thread. -.It Bq Er EOWNERDEAD -The lock was requested on an umutex where the -.Dv m_owner -field was set to the -.Dv UMUTEX_RB_OWNERDEAD -value, indicating terminated robust mutex. -The lock was granted to the caller, so this error in fact -indicates success with additional conditions. -.It Bq Er ENOTRECOVERABLE -The lock was requested on an umutex which -.Dv m_owner -field is equal to the -.Dv UMUTEX_RB_NOTRECOV -value, indicating abandoned robust mutex after termination. -The lock was not granted to the caller. -.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 -sub-requests of the -.Dv UMTX_OP_SHM -request, there is no shared memory object associated with the provided key. -.It Bq Er ENOMEM -The -.Dv UMTX_SHM_CREAT -sub-request of the -.Dv UMTX_OP_SHM -request cannot be satisfied, because allocation of the shared memory object -would exceed the -.Dv RLIMIT_UMTXP -resource limit, see -.Xr setrlimit 2 . -.It Bq Er EAGAIN -The maximum number of readers -.Dv ( URWLOCK_MAX_READERS ) -were already granted ownership of the given -.Vt struct rwlock -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 a timeout in the -.Fa uaddr -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 a 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 a restartable operation. -Mutex lock requests without timeout specified are restartable. -The error is not returned to userspace code since restart -is handled by usual adjustment of the instruction counter. -.El -.Sh SEE ALSO -.Xr clock_gettime 2 , -.Xr mmap 2 , -.Xr setrlimit 2 , -.Xr shm_open 2 , -.Xr sigaction 2 , -.Xr thr_exit 2 , -.Xr thr_kill 2 , -.Xr thr_kill2 2 , -.Xr thr_new 2 , -.Xr thr_self 2 , -.Xr thr_set_name 2 , -.Xr signal 3 -.Sh STANDARDS -The -.Fn _umtx_op -system call is non-standard and is used by the -.Lb libthr -to implement -.St -p1003.1-2001 -.Xr pthread 3 -functionality. -.Sh BUGS -A window between a unlocking robust mutex and resetting the pointer in the -.Dv robust_inact_offset -member of the registered -.Vt struct umtx_robust_lists_params -allows another thread to destroy the mutex, thus making the kernel inspect -freed or reused memory. -The -.Li libthr -implementation is only vulnerable to this race when operating on -a shared mutex. -A possible fix for the current implementation is to strengthen the checks -for shared mutexes before terminating them, in particular, verifying -that the mutex memory is mapped from a shared memory object allocated -by the -.Dv UMTX_OP_SHM -request. -This is not done because it is believed that the race is adequately -covered by other consistency checks, while adding the check would -prevent alternative implementations of -.Li libpthread . |