xref: /freebsd/lib/libsys/_umtx_op.2 (revision d15f2551b25f79ddcbe289faa95e655100b952da)
1.\" Copyright (c) 2016 The FreeBSD Foundation
2.\"
3.\" This documentation was written by
4.\" Konstantin Belousov <kib@FreeBSD.org> under sponsorship
5.\" from the FreeBSD Foundation.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\"    notice, this list of conditions and the following disclaimer.
12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\"    notice, this list of conditions and the following disclaimer in the
14.\"    documentation and/or other materials provided with the distribution.
15.\"
16.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
17.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
20.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26.\" SUCH DAMAGE.
27.\"
28.Dd November 23, 2020
29.Dt _UMTX_OP 2
30.Os
31.Sh NAME
32.Nm _umtx_op
33.Nd interface for implementation of userspace threading synchronization primitives
34.Sh LIBRARY
35.Lb libc
36.Sh SYNOPSIS
37.In sys/types.h
38.In sys/umtx.h
39.Ft int
40.Fn _umtx_op "void *obj" "int op" "u_long val" "void *uaddr" "void *uaddr2"
41.Sh DESCRIPTION
42The
43.Fn _umtx_op
44system call provides kernel support for userspace implementation of
45the threading synchronization primitives.
46The
47.Lb libthr
48uses the syscall to implement
49.St -p1003.1-2001
50pthread locks, like mutexes, condition variables and so on.
51.Ss STRUCTURES
52The operations, performed by the
53.Fn _umtx_op
54syscall, operate on userspace objects which are described
55by the following structures.
56Reserved fields and paddings are omitted.
57All objects require ABI-mandated alignment, but this is not currently
58enforced consistently on all architectures.
59.Pp
60The following flags are defined for flag fields of all structures:
61.Bl -tag -width indent
62.It Dv USYNC_PROCESS_SHARED
63Allow selection of the process-shared sleep queue for the thread sleep
64container, when the lock ownership cannot be granted immediately,
65and the operation must sleep.
66The process-shared or process-private sleep queue is selected based on
67the attributes of the memory mapping which contains the first byte of
68the structure, see
69.Xr mmap 2 .
70Otherwise, if the flag is not specified, the process-private sleep queue
71is selected regardless of the memory mapping attributes, as an optimization.
72.Pp
73See the
74.Sx SLEEP QUEUES
75subsection below for more details on sleep queues.
76.El
77.Bl -hang -offset indent
78.It Sy Mutex
79.Bd -literal
80struct umutex {
81	volatile lwpid_t m_owner;
82	uint32_t         m_flags;
83	uint32_t         m_ceilings[2];
84	uintptr_t        m_rb_lnk;
85};
86.Ed
87.Pp
88The
89.Dv m_owner
90field is the actual lock.
91It contains either the thread identifier of the lock owner in the
92locked state, or zero when the lock is unowned.
93The highest bit set indicates that there is contention on the lock.
94The constants are defined for special values:
95.Bl -tag -width indent
96.It Dv UMUTEX_UNOWNED
97Zero, the value stored in the unowned lock.
98.It Dv UMUTEX_CONTESTED
99The contention indicator.
100.It Dv UMUTEX_RB_OWNERDEAD
101A thread owning the robust mutex terminated.
102The mutex is in unlocked state.
103.It Dv UMUTEX_RB_NOTRECOV
104The robust mutex is in a non-recoverable state.
105It cannot be locked until reinitialized.
106.El
107.Pp
108The
109.Dv m_flags
110field may contain the following umutex-specific flags, in addition to
111the common flags:
112.Bl -tag -width indent
113.It Dv UMUTEX_PRIO_INHERIT
114Mutex implements
115.Em Priority Inheritance
116protocol.
117.It Dv UMUTEX_PRIO_PROTECT
118Mutex implements
119.Em Priority Protection
120protocol.
121.It Dv UMUTEX_ROBUST
122Mutex is robust, as described in the
123.Sx ROBUST UMUTEXES
124section below.
125.It Dv UMUTEX_NONCONSISTENT
126Robust mutex is in a transient non-consistent state.
127Not used by kernel.
128.El
129.Pp
130In the manual page, mutexes not having
131.Dv UMUTEX_PRIO_INHERIT
132and
133.Dv UMUTEX_PRIO_PROTECT
134flags set, are called normal mutexes.
135Each type of mutex
136.Pq normal, priority-inherited, and priority-protected
137has a separate sleep queue associated
138with the given key.
139.Pp
140For priority protected mutexes, the
141.Dv m_ceilings
142array contains priority ceiling values.
143The
144.Dv m_ceilings[0]
145is the ceiling value for the mutex, as specified by
146.St -p1003.1-2008
147for the
148.Em Priority Protected
149mutex protocol.
150The
151.Dv m_ceilings[1]
152is used only for the unlock of a priority protected mutex, when
153unlock is done in an order other than the reversed lock order.
154In this case,
155.Dv m_ceilings[1]
156must contain the ceiling value for the last locked priority protected
157mutex, for proper priority reassignment.
158If, instead, the unlocking mutex was the last priority propagated
159mutex locked by the thread,
160.Dv m_ceilings[1]
161should contain \-1.
162This is required because kernel does not maintain the ordered lock list.
163.It Sy Condition variable
164.Bd -literal
165struct ucond {
166	volatile uint32_t c_has_waiters;
167	uint32_t          c_flags;
168	uint32_t          c_clockid;
169};
170.Ed
171.Pp
172A non-zero
173.Dv c_has_waiters
174value indicates that there are in-kernel waiters for the condition,
175executing the
176.Dv UMTX_OP_CV_WAIT
177request.
178.Pp
179The
180.Dv c_flags
181field contains flags.
182Only the common flags
183.Pq Dv USYNC_PROCESS_SHARED
184are defined for ucond.
185.Pp
186The
187.Dv c_clockid
188member provides the clock identifier to use for timeout, when the
189.Dv UMTX_OP_CV_WAIT
190request has both the
191.Dv CVWAIT_CLOCKID
192flag and the timeout specified.
193Valid clock identifiers are a subset of those for
194.Xr clock_gettime 2 :
195.Bl -bullet -compact
196.It
197.Dv CLOCK_MONOTONIC
198.It
199.Dv CLOCK_MONOTONIC_FAST
200.It
201.Dv CLOCK_MONOTONIC_PRECISE
202.It
203.Dv CLOCK_PROF
204.It
205.Dv CLOCK_REALTIME
206.It
207.Dv CLOCK_REALTIME_FAST
208.It
209.Dv CLOCK_REALTIME_PRECISE
210.It
211.Dv CLOCK_SECOND
212.It
213.Dv CLOCK_TAI
214.It
215.Dv CLOCK_UPTIME
216.It
217.Dv CLOCK_UPTIME_FAST
218.It
219.Dv CLOCK_UPTIME_PRECISE
220.It
221.Dv CLOCK_VIRTUAL
222.El
223.It Sy Reader/writer lock
224.Bd -literal
225struct urwlock {
226	volatile int32_t rw_state;
227	uint32_t         rw_flags;
228	uint32_t         rw_blocked_readers;
229	uint32_t         rw_blocked_writers;
230};
231.Ed
232.Pp
233The
234.Dv rw_state
235field is the actual lock.
236It contains both the flags and counter of the read locks which were
237granted.
238Names of the
239.Dv rw_state
240bits are following:
241.Bl -tag -width indent
242.It Dv URWLOCK_WRITE_OWNER
243Write lock was granted.
244.It Dv URWLOCK_WRITE_WAITERS
245There are write lock waiters.
246.It Dv URWLOCK_READ_WAITERS
247There are read lock waiters.
248.It Dv URWLOCK_READER_COUNT(c)
249Returns the count of currently granted read locks.
250.El
251.Pp
252At any given time there may be only one thread to which the writer lock
253is granted on the
254.Vt struct rwlock ,
255and no threads are granted read lock.
256Or, at the given time, up to
257.Dv URWLOCK_MAX_READERS
258threads may be granted the read lock simultaneously, but write lock is
259not granted to any thread.
260.Pp
261The following flags for the
262.Dv rw_flags
263member of
264.Vt struct urwlock
265are defined, in addition to the common flags:
266.Bl -tag -width indent
267.It Dv URWLOCK_PREFER_READER
268If specified, immediately grant read lock requests when
269.Dv urwlock
270is already read-locked, even in presence of unsatisfied write
271lock requests.
272By default, if there is a write lock waiter, further read requests are
273not granted, to prevent unfair write lock waiter starvation.
274.El
275.Pp
276The
277.Dv rw_blocked_readers
278and
279.Dv rw_blocked_writers
280members contain the count of threads which are sleeping in kernel,
281waiting for the associated request type to be granted.
282The fields are used by kernel to update the
283.Dv URWLOCK_READ_WAITERS
284and
285.Dv URWLOCK_WRITE_WAITERS
286flags of the
287.Dv rw_state
288lock after requesting thread was woken up.
289.It Sy Semaphore
290.Bd -literal
291struct _usem2 {
292	volatile uint32_t _count;
293	uint32_t          _flags;
294};
295.Ed
296.Pp
297The
298.Dv _count
299word represents a counting semaphore.
300A non-zero value indicates an unlocked (posted) semaphore, while zero
301represents the locked state.
302The maximal supported semaphore count is
303.Dv USEM_MAX_COUNT .
304.Pp
305The
306.Dv _count
307word, besides the counter of posts (unlocks), also contains the
308.Dv USEM_HAS_WAITERS
309bit, which indicates that locked semaphore has waiting threads.
310.Pp
311The
312.Dv USEM_COUNT()
313macro, applied to the
314.Dv _count
315word, returns the current semaphore counter, which is the number of posts
316issued on the semaphore.
317.Pp
318The following bits for the
319.Dv _flags
320member of
321.Vt struct _usem2
322are defined, in addition to the common flags:
323.Bl -tag -width indent
324.It Dv USEM_NAMED
325Flag is ignored by kernel.
326.El
327.It Sy Timeout parameter
328.Bd -literal
329struct _umtx_time {
330	struct timespec _timeout;
331	uint32_t        _flags;
332	uint32_t        _clockid;
333};
334.Ed
335.Pp
336Several
337.Fn _umtx_op
338operations allow the blocking time to be limited, failing the request
339if it cannot be satisfied in the specified time period.
340The timeout is specified by passing either the address of
341.Vt struct timespec ,
342or its extended variant,
343.Vt struct _umtx_time ,
344as the
345.Fa uaddr2
346argument of
347.Fn _umtx_op .
348They are distinguished by the
349.Fa uaddr
350value, which must be equal to the size of the structure pointed to by
351.Fa uaddr2 ,
352casted to
353.Vt uintptr_t .
354.Pp
355The
356.Dv _timeout
357member specifies the time when the timeout should occur.
358Legal values for clock identifier
359.Dv _clockid
360are shared with the
361.Fa clock_id
362argument to the
363.Xr clock_gettime 2
364function,
365and use the same underlying clocks.
366The specified clock is used to obtain the current time value.
367Interval counting is always performed by the monotonic wall clock.
368.Pp
369The
370.Dv _flags
371argument allows the following flags to further define the timeout behaviour:
372.Bl -tag -width indent
373.It Dv UMTX_ABSTIME
374The
375.Dv _timeout
376value is the absolute time.
377The thread will be unblocked and the request failed when specified
378clock value is equal or exceeds the
379.Dv _timeout.
380.Pp
381If the flag is absent, the timeout value is relative, that is the amount
382of time, measured by the monotonic wall clock from the moment of the request
383start.
384.El
385.El
386.Ss SLEEP QUEUES
387When a locking request cannot be immediately satisfied, the thread is
388typically put to
389.Em sleep ,
390which is a non-runnable state terminated by the
391.Em wake
392operation.
393Lock operations include a
394.Em try
395variant which returns an error rather than sleeping if the lock cannot
396be obtained.
397Also,
398.Fn _umtx_op
399provides requests which explicitly put the thread to sleep.
400.Pp
401Wakes need to know which threads to make runnable, so sleeping threads
402are grouped into containers called
403.Em sleep queues .
404A sleep queue is identified by a key, which for
405.Fn _umtx_op
406is defined as the physical address of some variable.
407Note that the
408.Em physical
409address is used, which means that same variable mapped multiple
410times will give one key value.
411This mechanism enables the construction of
412.Em process-shared
413locks.
414.Pp
415A related attribute of the key is shareability.
416Some requests always interpret keys as private for the current process,
417creating sleep queues with the scope of the current process even if
418the memory is shared.
419Others either select the shareability automatically from the
420mapping attributes, or take additional input as the
421.Dv USYNC_PROCESS_SHARED
422common flag.
423This is done as optimization, allowing the lock scope to be limited
424regardless of the kind of backing memory.
425.Pp
426Only the address of the start byte of the variable specified as key is
427important for determining corresponding sleep queue.
428The size of the variable does not matter, so, for example, sleep on the same
429address interpreted as
430.Vt uint32_t
431and
432.Vt long
433on a little-endian 64-bit platform would collide.
434.Pp
435The last attribute of the key is the object type.
436The sleep queue to which a sleeping thread is assigned is an individual
437one for simple wait requests, mutexes, rwlocks, condvars and other
438primitives, even when the physical address of the key is same.
439.Pp
440When waking up a limited number of threads from a given sleep queue,
441the highest priority threads that have been blocked for the longest on
442the queue are selected.
443.Ss ROBUST UMUTEXES
444The
445.Em robust umutexes
446are provided as a substrate for a userspace library to implement
447.Tn POSIX
448robust mutexes.
449A robust umutex must have the
450.Dv UMUTEX_ROBUST
451flag set.
452.Pp
453On thread termination, the kernel walks two lists of mutexes.
454The two lists head addresses must be provided by a prior call to
455.Dv UMTX_OP_ROBUST_LISTS
456request.
457The lists are singly-linked.
458The link to next element is provided by the
459.Dv m_rb_lnk
460member of the
461.Vt struct umutex .
462.Pp
463Robust list processing is aborted if the kernel finds a mutex
464with any of the following conditions:
465.Bl -dash -offset indent -compact
466.It
467the
468.Dv UMUTEX_ROBUST
469flag is not set
470.It
471not owned by the current thread, except when the mutex is pointed to
472by the
473.Dv robust_inactive
474member of the
475.Vt struct umtx_robust_lists_params ,
476registered for the current thread
477.It
478the combination of mutex flags is invalid
479.It
480read of the umutex memory faults
481.It
482the list length limit described in
483.Xr libthr 3
484is reached.
485.El
486.Pp
487Every mutex in both lists is unlocked as if the
488.Dv UMTX_OP_MUTEX_UNLOCK
489request is performed on it, but instead of the
490.Dv UMUTEX_UNOWNED
491value, the
492.Dv m_owner
493field is written with the
494.Dv UMUTEX_RB_OWNERDEAD
495value.
496When a mutex in the
497.Dv UMUTEX_RB_OWNERDEAD
498state is locked by kernel due to the
499.Dv UMTX_OP_MUTEX_TRYLOCK
500and
501.Dv UMTX_OP_MUTEX_LOCK
502requests, the lock is granted and
503.Er EOWNERDEAD
504error is returned.
505.Pp
506Also, the kernel handles the
507.Dv UMUTEX_RB_NOTRECOV
508value of
509.Dv the m_owner
510field specially, always returning the
511.Er ENOTRECOVERABLE
512error for lock attempts, without granting the lock.
513.Ss OPERATIONS
514The following operations, requested by the
515.Fa op
516argument to the function, are implemented:
517.Bl -tag -width indent
518.It Dv UMTX_OP_WAIT
519Wait.
520The arguments for the request are:
521.Bl -tag -width "obj"
522.It Fa obj
523Pointer to a variable of type
524.Vt long .
525.It Fa val
526Current value of the
527.Dv *obj .
528.El
529.Pp
530The current value of the variable pointed to by the
531.Fa obj
532argument is compared with the
533.Fa val .
534If they are equal, the requesting thread is put to interruptible sleep
535until woken up or the optionally specified timeout expires.
536.Pp
537The comparison and sleep are atomic.
538In other words, if another thread writes a new value to
539.Dv *obj
540and then issues
541.Dv UMTX_OP_WAKE ,
542the request is guaranteed to not miss the wakeup,
543which might otherwise happen between comparison and blocking.
544.Pp
545The physical address of memory where the
546.Fa *obj
547variable is located, is used as a key to index sleeping threads.
548.Pp
549The read of the current value of the
550.Dv *obj
551variable is not guarded by barriers.
552In particular, it is the user's duty to ensure the lock acquire
553and release memory semantics, if the
554.Dv UMTX_OP_WAIT
555and
556.Dv UMTX_OP_WAKE
557requests are used as a substrate for implementing a simple lock.
558.Pp
559The request is not restartable.
560An unblocked signal delivered during the wait always results in sleep
561interruption and
562.Er EINTR
563error.
564.Pp
565Optionally, a timeout for the request may be specified.
566.It Dv UMTX_OP_WAKE
567Wake the threads possibly sleeping due to
568.Dv UMTX_OP_WAIT .
569The arguments for the request are:
570.Bl -tag -width "obj"
571.It Fa obj
572Pointer to a variable, used as a key to find sleeping threads.
573.It Fa val
574Up to
575.Fa val
576threads are woken up by this request.
577Specify
578.Dv INT_MAX
579to wake up all waiters.
580.El
581.It Dv UMTX_OP_MUTEX_TRYLOCK
582Try to lock umutex.
583The arguments to the request are:
584.Bl -tag -width "obj"
585.It Fa obj
586Pointer to the umutex.
587.El
588.Pp
589Operates same as the
590.Dv UMTX_OP_MUTEX_LOCK
591request, but returns
592.Er EBUSY
593instead of sleeping if the lock cannot be obtained immediately.
594.It Dv UMTX_OP_MUTEX_LOCK
595Lock umutex.
596The arguments to the request are:
597.Bl -tag -width "obj"
598.It Fa obj
599Pointer to the umutex.
600.El
601.Pp
602Locking is performed by writing the current thread id into the
603.Dv m_owner
604word of the
605.Vt struct umutex .
606The write is atomic, preserves the
607.Dv UMUTEX_CONTESTED
608contention indicator, and provides the acquire barrier for
609lock entrance semantic.
610.Pp
611If the lock cannot be obtained immediately because another thread owns
612the lock, the current thread is put to sleep, with
613.Dv UMUTEX_CONTESTED
614bit set before.
615Upon wake up, the lock conditions are re-tested.
616.Pp
617The request adheres to the priority protection or inheritance protocol
618of the mutex, specified by the
619.Dv UMUTEX_PRIO_PROTECT
620or
621.Dv UMUTEX_PRIO_INHERIT
622flag, respectively.
623.Pp
624Optionally, a timeout for the request may be specified.
625.Pp
626A request with a timeout specified is not restartable.
627An unblocked signal delivered during the wait always results in sleep
628interruption and
629.Er EINTR
630error.
631A request without timeout specified is always restarted after return
632from a signal handler.
633.It Dv UMTX_OP_MUTEX_UNLOCK
634Unlock umutex.
635The arguments to the request are:
636.Bl -tag -width "obj"
637.It Fa obj
638Pointer to the umutex.
639.El
640.Pp
641Unlocks the mutex, by writing
642.Dv UMUTEX_UNOWNED
643(zero) value into
644.Dv m_owner
645word of the
646.Vt struct umutex .
647The write is done with a release barrier, to provide lock leave semantic.
648.Pp
649If there are threads sleeping in the sleep queue associated with the
650umutex, one thread is woken up.
651If more than one thread sleeps in the sleep queue, the
652.Dv UMUTEX_CONTESTED
653bit is set together with the write of the
654.Dv UMUTEX_UNOWNED
655value into
656.Dv m_owner .
657.Pp
658The request adheres to the priority protection or inheritance protocol
659of the mutex, specified by the
660.Dv UMUTEX_PRIO_PROTECT
661or
662.Dv UMUTEX_PRIO_INHERIT
663flag, respectively.
664See description of the
665.Dv m_ceilings
666member of the
667.Vt struct umutex
668structure for additional details of the request operation on the
669priority protected protocol mutex.
670.It Dv UMTX_OP_SET_CEILING
671Set ceiling for the priority protected umutex.
672The arguments to the request are:
673.Bl -tag -width "uaddr"
674.It Fa obj
675Pointer to the umutex.
676.It Fa val
677New ceiling value.
678.It Fa uaddr
679Address of a variable of type
680.Vt uint32_t .
681If not
682.Dv NULL
683and the update was successful, the previous ceiling value is
684written to the location pointed to by
685.Fa uaddr .
686.El
687.Pp
688The request locks the umutex pointed to by the
689.Fa obj
690parameter, waiting for the lock if not immediately available.
691After the lock is obtained, the new ceiling value
692.Fa val
693is written to the
694.Dv m_ceilings[0]
695member of the
696.Vt struct umutex,
697after which the umutex is unlocked.
698.Pp
699The locking does not adhere to the priority protect protocol,
700to conform to the
701.Tn POSIX
702requirements for the
703.Xr pthread_mutex_setprioceiling 3
704interface.
705.It Dv UMTX_OP_CV_WAIT
706Wait for a condition.
707The arguments to the request are:
708.Bl -tag -width "uaddr2"
709.It Fa obj
710Pointer to the
711.Vt struct ucond .
712.It Fa val
713Request flags, see below.
714.It Fa uaddr
715Pointer to the umutex.
716.It Fa uaddr2
717Optional pointer to a
718.Vt struct timespec
719for timeout specification.
720.El
721.Pp
722The request must be issued by the thread owning the mutex pointed to
723by the
724.Fa uaddr
725argument.
726The
727.Dv c_hash_waiters
728member of the
729.Vt struct ucond ,
730pointed to by the
731.Fa obj
732argument, is set to an arbitrary non-zero value, after which the
733.Fa uaddr
734mutex is unlocked (following the appropriate protocol), and
735the current thread is put to sleep on the sleep queue keyed by
736the
737.Fa obj
738argument.
739The operations are performed atomically.
740It is guaranteed to not miss a wakeup from
741.Dv UMTX_OP_CV_SIGNAL
742or
743.Dv UMTX_OP_CV_BROADCAST
744sent between mutex unlock and putting the current thread on the sleep queue.
745.Pp
746Upon wakeup, if the timeout expired and no other threads are sleeping in
747the same sleep queue, the
748.Dv c_hash_waiters
749member is cleared.
750After wakeup, the
751.Fa uaddr
752umutex is not relocked.
753.Pp
754The following flags are defined:
755.Bl -tag -width "CVWAIT_UMTX_TIME"
756.It Dv CVWAIT_ABSTIME
757Timeout is absolute.
758.It Dv CVWAIT_CLOCKID
759Clockid is provided.
760.It Dv CVWAIT_UMTX_TIME
761Timeout is specified by
762.Vt struct umtx_time
763.El
764.Pp
765Optionally, a timeout for the request may be specified.
766If the
767.Dv CVWAIT_UMTX_TIME
768flag is not passed, then, unlike other requests,
769the timeout value is specified directly by a
770.Vt struct timespec ,
771pointed to by the
772.Fa uaddr2
773argument.
774If the
775.Dv CVWAIT_CLOCKID
776flag is provided, the timeout uses the clock from the
777.Dv c_clockid
778member of the
779.Vt struct ucond ,
780pointed to by
781.Fa obj
782argument.
783Otherwise,
784.Dv CLOCK_REALTIME
785is used, regardless of the clock identifier possibly specified in the
786.Vt struct _umtx_time .
787If the
788.Dv CVWAIT_ABSTIME
789flag is supplied, the timeout specifies absolute time value, otherwise
790it denotes a relative time interval.
791.Pp
792Alternatively, if the
793.Dv CVWAIT_UMTX_TIME
794flag is passed, then the
795.Dv CVWAIT_CLOCKID
796and
797.Dv CVWAIT_ABSTIME
798flags must be not passed.
799In this case, the
800.Fa uaddr2
801points to the
802.Va struct umtx_time
803structure which specifes the timeout and clock identifier.
804.Pp
805The request is not restartable.
806An unblocked signal delivered during
807the wait always results in sleep interruption and
808.Er EINTR
809error.
810.It Dv UMTX_OP_CV_SIGNAL
811Wake up one condition waiter.
812The arguments to the request are:
813.Bl -tag -width "obj"
814.It Fa obj
815Pointer to
816.Vt struct ucond .
817.El
818.Pp
819The request wakes up at most one thread sleeping on the sleep queue keyed
820by the
821.Fa obj
822argument.
823If the woken up thread was the last on the sleep queue, the
824.Dv c_has_waiters
825member of the
826.Vt struct ucond
827is cleared.
828.It Dv UMTX_OP_CV_BROADCAST
829Wake up all condition waiters.
830The arguments to the request are:
831.Bl -tag -width "obj"
832.It Fa obj
833Pointer to
834.Vt struct ucond .
835.El
836.Pp
837The request wakes up all threads sleeping on the sleep queue keyed by the
838.Fa obj
839argument.
840The
841.Dv c_has_waiters
842member of the
843.Vt struct ucond
844is cleared.
845.It Dv UMTX_OP_WAIT_UINT
846Same as
847.Dv UMTX_OP_WAIT ,
848but the type of the variable pointed to by
849.Fa obj
850is
851.Vt u_int
852.Pq a 32-bit integer .
853.It Dv UMTX_OP_RW_RDLOCK
854Read-lock a
855.Vt struct rwlock
856lock.
857The arguments to the request are:
858.Bl -tag -width "obj"
859.It Fa obj
860Pointer to the lock (of type
861.Vt struct rwlock )
862to be read-locked.
863.It Fa val
864Additional flags to augment locking behaviour.
865The valid flags in the
866.Fa val
867argument are:
868.Bl -tag -width indent
869.It Dv URWLOCK_PREFER_READER
870.El
871.El
872.Pp
873The request obtains the read lock on the specified
874.Vt struct rwlock
875by incrementing the count of readers in the
876.Dv rw_state
877word of the structure.
878If the
879.Dv URWLOCK_WRITE_OWNER
880bit is set in the word
881.Dv rw_state ,
882the lock was granted to a writer which has not yet relinquished
883its ownership.
884In this case the current thread is put to sleep until it makes sense to
885retry.
886.Pp
887If the
888.Dv URWLOCK_PREFER_READER
889flag is set either in the
890.Dv rw_flags
891word of the structure, or in the
892.Fa val
893argument of the request, the presence of the threads trying to obtain
894the write lock on the same structure does not prevent the current thread
895from trying to obtain the read lock.
896Otherwise, if the flag is not set, and the
897.Dv URWLOCK_WRITE_WAITERS
898flag is set in
899.Dv rw_state ,
900the current thread does not attempt to obtain read-lock.
901Instead it sets the
902.Dv URWLOCK_READ_WAITERS
903in the
904.Dv rw_state
905word and puts itself to sleep on corresponding sleep queue.
906Upon wakeup, the locking conditions are re-evaluated.
907.Pp
908Optionally, a timeout for the request may be specified.
909.Pp
910The request is not restartable.
911An unblocked signal delivered during the wait always results in sleep
912interruption and
913.Er EINTR
914error.
915.It Dv UMTX_OP_RW_WRLOCK
916Write-lock a
917.Vt struct rwlock
918lock.
919The arguments to the request are:
920.Bl -tag -width "obj"
921.It Fa obj
922Pointer to the lock (of type
923.Vt struct rwlock )
924to be write-locked.
925.El
926.Pp
927The request obtains a write lock on the specified
928.Vt struct rwlock ,
929by setting the
930.Dv URWLOCK_WRITE_OWNER
931bit in the
932.Dv rw_state
933word of the structure.
934If there is already a write lock owner, as indicated by the
935.Dv URWLOCK_WRITE_OWNER
936bit being set, or there are read lock owners, as indicated
937by the read-lock counter, the current thread does not attempt to
938obtain the write-lock.
939Instead it sets the
940.Dv URWLOCK_WRITE_WAITERS
941in the
942.Dv rw_state
943word and puts itself to sleep on corresponding sleep queue.
944Upon wakeup, the locking conditions are re-evaluated.
945.Pp
946Optionally, a timeout for the request may be specified.
947.Pp
948The request is not restartable.
949An unblocked signal delivered during the wait always results in sleep
950interruption and
951.Er EINTR
952error.
953.It Dv UMTX_OP_RW_UNLOCK
954Unlock rwlock.
955The arguments to the request are:
956.Bl -tag -width "obj"
957.It Fa obj
958Pointer to the lock (of type
959.Vt struct rwlock )
960to be unlocked.
961.El
962.Pp
963The unlock type (read or write) is determined by the
964current lock state.
965Note that the
966.Vt struct rwlock
967does not save information about the identity of the thread which
968acquired the lock.
969.Pp
970If there are pending writers after the unlock, and the
971.Dv URWLOCK_PREFER_READER
972flag is not set in the
973.Dv rw_flags
974member of the
975.Fa *obj
976structure, one writer is woken up, selected as described in the
977.Sx SLEEP QUEUES
978subsection.
979If the
980.Dv URWLOCK_PREFER_READER
981flag is set, a pending writer is woken up only if there is
982no pending readers.
983.Pp
984If there are no pending writers, or, in the case that the
985.Dv URWLOCK_PREFER_READER
986flag is set, then all pending readers are woken up by unlock.
987.It Dv UMTX_OP_WAIT_UINT_PRIVATE
988Same as
989.Dv UMTX_OP_WAIT_UINT ,
990but unconditionally select the process-private sleep queue.
991.It Dv UMTX_OP_WAKE_PRIVATE
992Same as
993.Dv UMTX_OP_WAKE ,
994but unconditionally select the process-private sleep queue.
995.It Dv UMTX_OP_MUTEX_WAIT
996Wait for mutex availability.
997The arguments to the request are:
998.Bl -tag -width "obj"
999.It Fa obj
1000Address of the mutex.
1001.El
1002.Pp
1003Similarly to the
1004.Dv UMTX_OP_MUTEX_LOCK ,
1005put the requesting thread to sleep if the mutex lock cannot be obtained
1006immediately.
1007The
1008.Dv UMUTEX_CONTESTED
1009bit is set in the
1010.Dv m_owner
1011word of the mutex to indicate that there is a waiter, before the thread
1012is added to the sleep queue.
1013Unlike the
1014.Dv UMTX_OP_MUTEX_LOCK
1015request, the lock is not obtained.
1016.Pp
1017The operation is not implemented for priority protected and
1018priority inherited protocol mutexes.
1019.Pp
1020Optionally, a timeout for the request may be specified.
1021.Pp
1022A request with a timeout specified is not restartable.
1023An unblocked signal delivered during the wait always results in sleep
1024interruption and
1025.Er EINTR
1026error.
1027A request without a timeout automatically restarts if the signal disposition
1028requested restart via the
1029.Dv SA_RESTART
1030flag in
1031.Vt struct sigaction
1032member
1033.Dv sa_flags .
1034.It Dv UMTX_OP_NWAKE_PRIVATE
1035Wake up a batch of sleeping threads.
1036The arguments to the request are:
1037.Bl -tag -width "obj"
1038.It Fa obj
1039Pointer to the array of pointers.
1040.It Fa val
1041Number of elements in the array pointed to by
1042.Fa obj .
1043.El
1044.Pp
1045For each element in the array pointed to by
1046.Fa obj ,
1047wakes up all threads waiting on the
1048.Em private
1049sleep queue with the key
1050being the byte addressed by the array element.
1051.It Dv UMTX_OP_MUTEX_WAKE
1052Check if a normal umutex is unlocked and wake up a waiter.
1053The arguments for the request are:
1054.Bl -tag -width "obj"
1055.It Fa obj
1056Pointer to the umutex.
1057.El
1058.Pp
1059If the
1060.Dv m_owner
1061word of the mutex pointed to by the
1062.Fa obj
1063argument indicates unowned mutex, which has its contention indicator bit
1064.Dv UMUTEX_CONTESTED
1065set, clear the bit and wake up one waiter in the sleep queue associated
1066with the byte addressed by the
1067.Fa obj ,
1068if any.
1069Only normal mutexes are supported by the request.
1070The sleep queue is always one for a normal mutex type.
1071.Pp
1072This request is deprecated in favor of
1073.Dv UMTX_OP_MUTEX_WAKE2
1074since mutexes using it cannot synchronize their own destruction.
1075That is, the
1076.Dv m_owner
1077word has already been set to
1078.Dv UMUTEX_UNOWNED
1079when this request is made,
1080so that another thread can lock, unlock and destroy the mutex
1081(if no other thread uses the mutex afterwards).
1082Clearing the
1083.Dv UMUTEX_CONTESTED
1084bit may then modify freed memory.
1085.It Dv UMTX_OP_MUTEX_WAKE2
1086Check if a umutex is unlocked and wake up a waiter.
1087The arguments for the request are:
1088.Bl -tag -width "obj"
1089.It Fa obj
1090Pointer to the umutex.
1091.It Fa val
1092The umutex flags.
1093.El
1094.Pp
1095The request does not read the
1096.Dv m_flags
1097member of the
1098.Vt struct umutex ;
1099instead, the
1100.Fa val
1101argument supplies flag information, in particular, to determine the
1102sleep queue where the waiters are found for wake up.
1103.Pp
1104If the mutex is unowned, one waiter is woken up.
1105.Pp
1106If the mutex memory cannot be accessed, all waiters are woken up.
1107.Pp
1108If there is more than one waiter on the sleep queue, or there is only
1109one waiter but the mutex is owned by a thread, the
1110.Dv UMUTEX_CONTESTED
1111bit is set in the
1112.Dv m_owner
1113word of the
1114.Vt struct umutex .
1115.It Dv UMTX_OP_SEM2_WAIT
1116Wait until semaphore is available.
1117The arguments to the request are:
1118.Bl -tag -width "obj"
1119.It Fa obj
1120Pointer to the semaphore (of type
1121.Vt struct _usem2 ) .
1122.It Fa uaddr
1123Size of the memory passed in via the
1124.Fa uaddr2
1125argument.
1126.It Fa uaddr2
1127Optional pointer to a structure of type
1128.Vt struct _umtx_time ,
1129which may be followed by a structure of type
1130.Vt struct timespec .
1131.El
1132.Pp
1133Put the requesting thread onto a sleep queue if the semaphore counter
1134is zero.
1135If the thread is put to sleep, the
1136.Dv USEM_HAS_WAITERS
1137bit is set in the
1138.Dv _count
1139word to indicate waiters.
1140The function returns either due to
1141.Dv _count
1142indicating the semaphore is available (non-zero count due to post),
1143or due to a wakeup.
1144The return does not guarantee that the semaphore is available,
1145nor does it consume the semaphore lock on successful return.
1146.Pp
1147Optionally, a timeout for the request may be specified.
1148.Pp
1149A request with non-absolute timeout value is not restartable.
1150An unblocked signal delivered during such wait results in sleep
1151interruption and
1152.Er EINTR
1153error.
1154.Pp
1155If
1156.Dv UMTX_ABSTIME
1157was not set, and the operation was interrupted and the caller passed in a
1158.Fa uaddr2
1159large enough to hold a
1160.Vt struct timespec
1161following the initial
1162.Vt struct _umtx_time ,
1163then the
1164.Vt struct timespec
1165is updated to contain the unslept amount.
1166.It Dv UMTX_OP_SEM2_WAKE
1167Wake up waiters on semaphore lock.
1168The arguments to the request are:
1169.Bl -tag -width "obj"
1170.It Fa obj
1171Pointer to the semaphore (of type
1172.Vt struct _usem2 ) .
1173.El
1174.Pp
1175The request wakes up one waiter for the semaphore lock.
1176The function does not increment the semaphore lock count.
1177If the
1178.Dv USEM_HAS_WAITERS
1179bit was set in the
1180.Dv _count
1181word, and the last sleeping thread was woken up, the bit is cleared.
1182.It Dv UMTX_OP_SHM
1183Manage anonymous
1184.Tn POSIX
1185shared memory objects (see
1186.Xr shm_open 2 ) ,
1187which can be attached to a byte of physical memory, mapped into the
1188process address space.
1189The objects are used to implement process-shared locks in
1190.Dv libthr .
1191.Pp
1192The
1193.Fa val
1194argument specifies the sub-request of the
1195.Dv UMTX_OP_SHM
1196request:
1197.Bl -tag -width indent
1198.It Dv UMTX_SHM_CREAT
1199Creates the anonymous shared memory object, which can be looked up
1200with the specified key
1201.Fa uaddr .
1202If the object associated with the
1203.Fa uaddr
1204key already exists, it is returned instead of creating a new object.
1205The object's size is one page.
1206On success, the file descriptor referencing the object is returned.
1207The descriptor can be used for mapping the object using
1208.Xr mmap 2 ,
1209or for other shared memory operations.
1210.It Dv UMTX_SHM_LOOKUP
1211Same as
1212.Dv UMTX_SHM_CREATE
1213request, but if there is no shared memory object associated with
1214the specified key
1215.Fa uaddr ,
1216an error is returned, and no new object is created.
1217.It Dv UMTX_SHM_DESTROY
1218De-associate the shared object with the specified key
1219.Fa uaddr .
1220The object is destroyed after the last open file descriptor is closed
1221and the last mapping for it is destroyed.
1222.It Dv UMTX_SHM_ALIVE
1223Checks whether there is a live shared object associated with the
1224supplied key
1225.Fa uaddr .
1226Returns zero if there is, and an error otherwise.
1227This request is an optimization of the
1228.Dv UMTX_SHM_LOOKUP
1229request.
1230It is cheaper when only the liveness of the associated object is asked
1231for, since no file descriptor is installed in the process fd table
1232on success.
1233.El
1234.Pp
1235The
1236.Fa uaddr
1237argument specifies the virtual address, which backing physical memory
1238byte identity is used as a key for the anonymous shared object
1239creation or lookup.
1240.It Dv UMTX_OP_ROBUST_LISTS
1241Register the list heads for the current thread's robust mutex lists.
1242The arguments to the request are:
1243.Bl -tag -width "uaddr"
1244.It Fa val
1245Size of the structure passed in the
1246.Fa uaddr
1247argument.
1248.It Fa uaddr
1249Pointer to the structure of type
1250.Vt struct umtx_robust_lists_params .
1251.El
1252.Pp
1253The structure is defined as
1254.Bd -literal
1255struct umtx_robust_lists_params {
1256	uintptr_t	robust_list_offset;
1257	uintptr_t	robust_priv_list_offset;
1258	uintptr_t	robust_inact_offset;
1259};
1260.Ed
1261.Pp
1262The
1263.Dv robust_list_offset
1264member contains address of the first element in the list of locked
1265robust shared mutexes.
1266The
1267.Dv robust_priv_list_offset
1268member contains address of the first element in the list of locked
1269robust private mutexes.
1270The private and shared robust locked lists are split to allow fast
1271termination of the shared list on fork, in the child.
1272.Pp
1273The
1274.Dv robust_inact_offset
1275contains a pointer to the mutex which might be locked in nearby future,
1276or might have been just unlocked.
1277It is typically set by the lock or unlock mutex implementation code
1278around the whole operation, since lists can be only changed race-free
1279when the thread owns the mutex.
1280The kernel inspects the
1281.Dv robust_inact_offset
1282in addition to walking the shared and private lists.
1283Also, the mutex pointed to by
1284.Dv robust_inact_offset
1285is handled more loosely at the thread termination time,
1286than other mutexes on the list.
1287That mutex is allowed to be not owned by the current thread,
1288in which case list processing is continued.
1289See
1290.Sx ROBUST UMUTEXES
1291subsection for details.
1292.It Dv UMTX_OP_GET_MIN_TIMEOUT
1293Writes out the current value of minimal umtx operations timeout,
1294in nanoseconds, into the long integer variable pointed to by
1295.Fa uaddr1 .
1296.It Dv UMTX_OP_SET_MIN_TIMEOUT
1297Set the minimal amount of time, in nanoseconds, the thread is required
1298to sleep for umtx operations specifying a timeout using absolute clocks.
1299The value is taken from the
1300.Fa val
1301argument of the call.
1302Zero means no minimum.
1303.El
1304.Pp
1305The
1306.Fa op
1307argument may be a bitwise OR of a single command from above with one or more of
1308the following flags:
1309.Bl -tag -width indent
1310.It Dv UMTX_OP__I386
1311Request i386 ABI compatibility from the native
1312.Nm
1313system call.
1314Specifically, this implies that:
1315.Bl -hang -offset indent
1316.It
1317.Fa obj
1318arguments that point to a word, point to a 32-bit integer.
1319.It
1320The
1321.Dv UMTX_OP_NWAKE_PRIVATE
1322.Fa obj
1323argument is a pointer to an array of 32-bit pointers.
1324.It
1325The
1326.Dv m_rb_lnk
1327member of
1328.Vt struct umutex
1329is a 32-bit pointer.
1330.It
1331.Vt struct timespec
1332uses a 32-bit time_t.
1333.El
1334.Pp
1335.Dv UMTX_OP__32BIT
1336has no effect if this flag is set.
1337This flag is valid for all architectures, but it is ignored on i386.
1338.It Dv UMTX_OP__32BIT
1339Request non-i386, 32-bit ABI compatibility from the native
1340.Nm
1341system call.
1342Specifically, this implies that:
1343.Bl -hang -offset indent
1344.It
1345.Fa obj
1346arguments that point to a word, point to a 32-bit integer.
1347.It
1348The
1349.Dv UMTX_OP_NWAKE_PRIVATE
1350.Fa obj
1351argument is a pointer to an array of 32-bit pointers.
1352.It
1353The
1354.Dv m_rb_lnk
1355member of
1356.Vt struct umutex
1357is a 32-bit pointer.
1358.It
1359.Vt struct timespec
1360uses a 64-bit time_t.
1361.El
1362.Pp
1363This flag has no effect if
1364.Dv UMTX_OP__I386
1365is set.
1366This flag is valid for all architectures.
1367.El
1368.Pp
1369Note that if any 32-bit ABI compatibility is being requested, then care must be
1370taken with robust lists.
1371A single thread may not mix 32-bit compatible robust lists with native
1372robust lists.
1373The first
1374.Dv UMTX_OP_ROBUST_LISTS
1375call in a given thread determines which ABI that thread will use for robust
1376lists going forward.
1377.Sh RETURN VALUES
1378If successful,
1379all requests, except
1380.Dv UMTX_SHM_CREAT
1381and
1382.Dv UMTX_SHM_LOOKUP
1383sub-requests of the
1384.Dv UMTX_OP_SHM
1385request, will return zero.
1386The
1387.Dv UMTX_SHM_CREAT
1388and
1389.Dv UMTX_SHM_LOOKUP
1390return a shared memory file descriptor on success.
1391On error \-1 is returned, and the
1392.Va errno
1393variable is set to indicate the error.
1394.Sh ERRORS
1395The
1396.Fn _umtx_op
1397operations can fail with the following errors:
1398.Bl -tag -width "[ETIMEDOUT]"
1399.It Bq Er EFAULT
1400One of the arguments point to invalid memory.
1401.It Bq Er EINVAL
1402The clock identifier, specified for the
1403.Vt struct _umtx_time
1404timeout parameter, or in the
1405.Dv c_clockid
1406member of
1407.Vt struct ucond,
1408is invalid.
1409.It Bq Er EINVAL
1410The type of the mutex, encoded by the
1411.Dv m_flags
1412member of
1413.Vt struct umutex ,
1414is invalid.
1415.It Bq Er EINVAL
1416The
1417.Dv m_owner
1418member of the
1419.Vt struct umutex
1420has changed the lock owner thread identifier during unlock.
1421.It Bq Er EINVAL
1422The
1423.Dv timeout.tv_sec
1424or
1425.Dv timeout.tv_nsec
1426member of
1427.Vt struct _umtx_time
1428is less than zero, or
1429.Dv timeout.tv_nsec
1430is greater than 1000000000.
1431.It Bq Er EINVAL
1432The
1433.Fa op
1434argument specifies invalid operation.
1435.It Bq Er EINVAL
1436The
1437.Fa uaddr
1438argument for the
1439.Dv UMTX_OP_SHM
1440request specifies invalid operation.
1441.It Bq Er EINVAL
1442The
1443.Dv UMTX_OP_SET_CEILING
1444request specifies non priority protected mutex.
1445.It Bq Er EINVAL
1446The new ceiling value for the
1447.Dv UMTX_OP_SET_CEILING
1448request, or one or more of the values read from the
1449.Dv m_ceilings
1450array during lock or unlock operations, is greater than
1451.Dv RTP_PRIO_MAX .
1452.It Bq Er EPERM
1453Unlock attempted on an object not owned by the current thread.
1454.It Bq Er EOWNERDEAD
1455The lock was requested on an umutex where the
1456.Dv m_owner
1457field was set to the
1458.Dv UMUTEX_RB_OWNERDEAD
1459value, indicating terminated robust mutex.
1460The lock was granted to the caller, so this error in fact
1461indicates success with additional conditions.
1462.It Bq Er ENOTRECOVERABLE
1463The lock was requested on an umutex which
1464.Dv m_owner
1465field is equal to the
1466.Dv UMUTEX_RB_NOTRECOV
1467value, indicating abandoned robust mutex after termination.
1468The lock was not granted to the caller.
1469.It Bq Er ENOTTY
1470The shared memory object, associated with the address passed to the
1471.Dv UMTX_SHM_ALIVE
1472sub-request of
1473.Dv UMTX_OP_SHM
1474request, was destroyed.
1475.It Bq Er ESRCH
1476For the
1477.Dv UMTX_SHM_LOOKUP ,
1478.Dv UMTX_SHM_DESTROY ,
1479and
1480.Dv UMTX_SHM_ALIVE
1481sub-requests of the
1482.Dv UMTX_OP_SHM
1483request, there is no shared memory object associated with the provided key.
1484.It Bq Er ENOMEM
1485The
1486.Dv UMTX_SHM_CREAT
1487sub-request of the
1488.Dv UMTX_OP_SHM
1489request cannot be satisfied, because allocation of the shared memory object
1490would exceed the
1491.Dv RLIMIT_UMTXP
1492resource limit, see
1493.Xr setrlimit 2 .
1494.It Bq Er EAGAIN
1495The maximum number of readers
1496.Dv ( URWLOCK_MAX_READERS )
1497were already granted ownership of the given
1498.Vt struct rwlock
1499for read.
1500.It Bq Er EBUSY
1501A try mutex lock operation was not able to obtain the lock.
1502.It Bq Er ETIMEDOUT
1503The request specified a timeout in the
1504.Fa uaddr
1505and
1506.Fa uaddr2
1507arguments, and timed out before obtaining the lock or being woken up.
1508.It Bq Er EINTR
1509A signal was delivered during wait, for a non-restartable operation.
1510Operations with timeouts are typically non-restartable, but timeouts
1511specified in absolute time may be restartable.
1512.It Bq Er ERESTART
1513A signal was delivered during wait, for a restartable operation.
1514Mutex lock requests without timeout specified are restartable.
1515The error is not returned to userspace code since restart
1516is handled by usual adjustment of the instruction counter.
1517.El
1518.Sh SEE ALSO
1519.Xr clock_gettime 2 ,
1520.Xr mmap 2 ,
1521.Xr setrlimit 2 ,
1522.Xr shm_open 2 ,
1523.Xr sigaction 2 ,
1524.Xr thr_exit 2 ,
1525.Xr thr_kill 2 ,
1526.Xr thr_kill2 2 ,
1527.Xr thr_new 2 ,
1528.Xr thr_self 2 ,
1529.Xr thr_set_name 2 ,
1530.Xr signal 3
1531.Sh STANDARDS
1532The
1533.Fn _umtx_op
1534system call is non-standard and is used by the
1535.Lb libthr
1536to implement
1537.St -p1003.1-2001
1538.Xr pthread 3
1539functionality.
1540.Sh BUGS
1541A window between a unlocking robust mutex and resetting the pointer in the
1542.Dv robust_inact_offset
1543member of the registered
1544.Vt struct umtx_robust_lists_params
1545allows another thread to destroy the mutex, thus making the kernel inspect
1546freed or reused memory.
1547The
1548.Li libthr
1549implementation is only vulnerable to this race when operating on
1550a shared mutex.
1551A possible fix for the current implementation is to strengthen the checks
1552for shared mutexes before terminating them, in particular, verifying
1553that the mutex memory is mapped from a shared memory object allocated
1554by the
1555.Dv UMTX_OP_SHM
1556request.
1557This is not done because it is believed that the race is adequately
1558covered by other consistency checks, while adding the check would
1559prevent alternative implementations of
1560.Li libpthread .
1561