xref: /freebsd/share/man/man4/ntsync.4 (revision 65251c43415aa0993b7d43962cbb71d772870c83)
1.\"
2.\" SPDX-License-Identifier: BSD-2-Clause
3.\"
4.\" Copyright 2026 The FreeBSD Foundation
5.\"
6.\" This documentation was written by Konstantin Belousov <kib@FreeBSD.org>
7.\" under sponsorship from the FreeBSD Foundation.
8.\"
9.Dd June 19, 2026
10.Dt NTSYNC 4
11.Os
12.Sh NAME
13.Nm ntsync
14.Nd NT-like synchronization operations device driver
15.Sh SYNOPSIS
16.In dev/ntsync/ntsync.h
17.Sh DESCRIPTION
18The
19.Nm
20device driver provides synchronization primitives that mimic the operations
21provided by the Windows NT kernel.
22The userspace interface is copied from the identically named driver written
23for the Linux kernel, with the goal of helping Wine implement Win32 API.
24.Pp
25The driver provides the
26.Pa /dev/ntsync
27special device node that handles
28.Xr ioctl 2
29requests of several groups:
30.Bl -tag -width "wait operations:"
31.It object creation:
32among them semaphores, mutexes, and events
33.It wait operations:
34waiting for the set of objects to become signaled, either all
35or any objects in the set can be waited for
36.El
37.Pp
38An
39.Xr open 2
40of the
41.Pa /dev/ntsync
42device returns the file descriptor which represents the synchronization
43domain.
44Each object created by the
45.Xr ioctl 2
46on the ntsync file descriptor belongs to it's domain.
47Wait requests must not mix the objects belonging to other domains.
48.Pp
49The synchronization objects are represented by file descriptors, each
50implementing type-specific set of ioctl requests.
51.Sh SEMAPHORES
52The semaphores operations usually take the
53.Bd -literal
54struct ntsync_sem_args {
55	uint32_t count;
56	uint32_t max;
57}
58.Ed
59as an argument.
60The semaphore requests are:
61.Bl -tag -width "NTSYNC_IOC_SEM_RELEASE"
62.It Dv NTSYNC_IOC_CREATE_SEM
63Creates the semaphore and returns the semaphore file descriptor.
64Must be issued on the
65.Pa /dev/ntsync
66file descriptor.
67.Pp
68Takes the
69.Va struct ntsync_sem_args
70argument, where
71.Dv count
72is the initial semaphore count, and
73.Dv max
74is the maximum allowed count.
75.It Dv NTSYNC_IOC_SEM_RELEASE
76Releases the semaphore.
77Takes the single
78.Va uint32_t
79value which is used to decrement the semaphore count.
80If the semaphore count reaches zero, the semaphore becomes signaled.
81.It Dv NTSYNC_IOC_SEM_READ
82Returns the current state of the semaphore in the
83.Va struct ntsync_sem_args .
84.El
85.Sh MUTEXES
86The mutexes operations usually take the
87.Bd -literal
88struct ntsync_mutex_args {
89	uint32_t owner;
90	uint32_t count;
91}
92.Ed
93as the argument.
94.Pp
95The mutex requests are:
96.Bl -tag -width "NTSYNC_IOC_CREATE_MUTEX"
97.It Dv NTSYNC_IOC_CREATE_MUTEX
98Creates the mutex and returns the mutex file descriptor.
99Must be issued on the
100.Pa /dev/ntsync
101file descriptor.
102.Pp
103Takes the
104.Va struct ntsync_mutex_args
105as the argument.
106The
107.Dv owner
108is an abstract 32bit number that identifies the current mutex owner.
109If
110.Dv owner
111is zero, the mutex is unowned, and
112.Dv count
113must be zero.
114If
115.Dv count
116is non-zero, indicating the owned mutex, a non-zero
117.Dv owner
118must be provided.
119.It Dv NTSYNC_IOC_MUTEX_UNLOCK
120Unlocks the mutex.
121Takes the
122.Va struct ntsync_mutex_args
123argument.
124.Pp
125The mutex must be owned by the argument's
126.Dv owner .
127Successful unlock decrements mutex' counter, and makes the mutex
128signaled and unowned if the counter reaches zero.
129.Pp
130The counter value before unlock is returned in the
131.Dv count
132member of the argument structure.
133.It Dv NTSYNC_IOC_MUTEX_KILL
134Abandon the mutex.
135Takes a single 32bit integer as the argument, indicating the current
136mutex owner.
137.Pp
138The specified owner must be equal to the current mutex owner.
139Then, the pending waiters are woken up, and get the
140.Ev EOWNERDEAD
141result.
142The mutex owner and counter are set to zero.
143.Pp
144The abandoned state is cleared by next successful wait on the mutex.
145.It Dv NTSYNC_IOC_MUTEX_READ
146Returns the current state of the mutex.
147Takes the
148.Va struct ntsync_mutex_args
149argument where the state is returned.
150For abandoned mutexes, the
151.Ev EOWNERDEAD
152error is returned in addition to the state.
153.El
154.Sh EVENTS
155The events operations usually take the
156.Bd -literal
157struct ntsync_event_args {
158	uint32_t manual;
159	uint32_t signaled;
160}
161.Ed
162.Pp
163The events requests are:
164.Bl -tag -width "NTSYNC_IOC_CREATE_EVENT"
165.It Dv NTSYNC_IOC_CREATE_EVENT
166Creates the event and returns the event file descriptor.
167Must be issued on the
168.Pa /dev/ntsync
169file descriptor.
170Takes the
171.Va struct ntsync_event_args
172argument.
173.Pp
174Events can be of two types: manual and automatic.
175Manual events needs to be reset by the request after being set.
176Automatic events are reset by the system after a wait is satisfied.
177.It Dv NTSYNC_IOC_EVENT_SET
178Set (arm) the event.
179Takes a 32bit integer argument where the state of the event before
180the operation is returned.
181.It Dv NTSYNC_IOC_EVENT_RESET
182Reset (dis-arms) the event.
183Takes a 32bit integer argument where the state of the event before
184the operation is returned.
185.It Dv NTSYNC_IOC_EVENT_PULSE
186Atomically sets the event, wakes up eligible waiters,
187and then resets the event.
188Takes a 32bit integer argument where the state of the event before
189the operation is returned.
190.Pp
191If the manual event is pulsed, it wakes up all waiters,
192after which it is reset.
193On the other hand, the automatic event is reset after
194waking up at most a single waiter.
195.It Dv NTSYNC_IOC_EVENT_READ
196Returns the current state of the event.
197Takes the
198.Va struct ntsync_event_args
199argument where the current event state is returned.
200.El
201.Sh WAIT OPERATIONS
202Wait operations take the
203.Bd -literal
204struct ntsync_wait_args {
205	uint64_t timeout;
206	uint64_t objs;
207	uint32_t count;
208	uint32_t index;
209	uint32_t flags;
210	uint32_t owner;
211	uint32_t alert;
212	uint32_t pad;
213}
214.Ed
215as the argument.
216.Pp
217The signaled state of the objects which cause the wait to
218become satisfied are consumed by the operation,
219e.g. the semaphore is acquired by incrementing its counter,
220the mutex is locked,
221and the manual event becomes not signaled.
222.Pp
223The
224.Dv timeout
225is in the nanoseconds.
226If
227.Dv timeout
228is zero, the wait request only returns when either the wait
229condition is satisfied, or a signal is queued.
230Otherwise, if the wait is not satisfied after the specified time,
231it is aborted anyway and the
232.Er ETIMEDOUT
233error is returned.
234.Pp
235The
236.Dv objs
237member points to the array of the synchronization object's file
238descriptors.
239Its size if passed in the
240.Dv count
241member.
242It might be as large as
243.Dv NTSYNC_MAX_WAIT_COUNT ,
244which is 64.
245.Pp
246The
247.Dv alert
248if non-zero specifies the event file descriptor,
249signaling of which finishes the wait regardless the state of
250other objects in the
251.Dv objs
252array.
253.Pp
254On non-error return from the wait requests, the
255.Dv index
256member contains the index of the signaled object that caused
257the wait request to be satisfied.
258If the object at the index is a semaphore, the
259.Dv owner
260member reports the owner of the signaled semaphore.
261If the
262.Dv alert
263event was signaled to abort the wait,
264.Dv index
265is set to
266.Dv count .
267.Pp
268The possible values for the
269.Va flags
270parameter are
271.Bl -tag -width "NTSYNC_WAIT_REALTIME"
272.It Dv NTSYNC_WAIT_REALTIME
273The specified timeout is for
274.Dv CLOCK_REALTIME
275absolute value, otherwise it is for
276.Dv CLOCK_MONOTONIC ,
277see
278.Xr clock_gettime 2 .
279.El
280.Pp
281The wait requests are:
282.Bl -tag -width "NTSYNC_IOC_WAIT_ANY"
283.It Dv NTSYNC_IOC_WAIT_ANY
284Wait for any of the objects to become signaled.
285.It Dv NTSYNC_IOC_WAIT_ALL
286Wait for all of the objects to become signaled.
287This means that the wait is satisfied only when all objects
288can be consumed together, which is done atomically.
289.Pp
290No duplicate objects are allowed in the
291.Dv objs
292array.
293The
294.Dv alert
295object is not allowed to be listed in the
296.Dv objs
297array.
298.El
299.Sh SEE ALSO
300Refer to the file
301.Pa Documentation/userspace-api/ntsync.rst
302in the Linux kernel sources for the Linux API reference,
303that was used for the implementation of the
304.Fx
305driver.
306.Sh HISTORY
307The
308.Nm
309driver and manual page first appeared in
310.Fx 15.2 .
311.Sh AUTHORS
312.An -nosplit
313The driver and the manual page were written by
314.An Konstantin Belousov Aq Mt kib@FreeBSD.org .
315