Training courses

Kernel and Embedded Linux

Bootlin training courses

Embedded Linux, kernel,
Yocto Project, Buildroot, real-time,
graphics, boot time, debugging...

Bootlin logo

Elixir Cross Referencer

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
.\"     $NetBSD: rumpuser.3,v 1.3 2019/03/08 08:24:41 wiz Exp $
.\"
.\" Copyright (c) 2013 Antti Kantee.  All rights reserved.
.\"
.\" 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 AUTHOR 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 AUTHOR 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.
.\"
.Dd August 24, 2014
.Dt RUMPUSER 3
.Os
.Sh NAME
.Nm rumpuser
.Nd rump kernel hypercall interface
.Sh LIBRARY
rump User Library (librumpuser, \-lrumpuser)
.Sh SYNOPSIS
.In rump/rumpuser.h
.Sh DESCRIPTION
The
.Nm
hypercall interfaces allow a rump kernel to access host resources.
A hypervisor implementation must implement the routines described in
this document to allow a rump kernel to run on the host.
The implementation included in
.Nx
is for POSIX-like hosts (*BSD, Linux, etc.).
This document is divided into sections based on the functionality
group of each hypercall.
.Pp
Since the hypercall interface is a C function interface, both the
rump kernel and the hypervisor must conform to the same ABI.
The interface itself attempts to assume as little as possible from
the type systems, and for example
.Vt off_t
is passed as
.Vt int64_t
and enums are passed as ints.
It is recommended that the hypervisor converts these to the native
types before starting to process the hypercall, for example by
assigning the ints back to enums.
.Sh UPCALLS AND RUMP KERNEL CONTEXT
A hypercall is always entered with the calling thread scheduled in
the rump kernel.
In case the hypercall intends to block while waiting for an event,
the hypervisor must first release the rump kernel scheduling context.
In other words, the rump kernel context is a resource and holding
on to it while waiting for a rump kernel event/resource may lead
to a deadlock.
Even when there is no possibility of deadlock in the strict sense
of the term, holding on to the rump kernel context while performing
a slow hypercall such as reading a device will prevent other threads
(including the clock interrupt) from using that rump kernel context.
.Pp
Releasing the context is done by calling the
.Fn hyp_backend_unschedule
upcall which the hypervisor received from rump kernel as a parameter
for
.Fn rumpuser_init .
Before a hypercall returns back to the rump kernel, the returning thread
must carry a rump kernel context.
In case the hypercall unscheduled itself, it must reschedule itself
by calling
.Fn hyp_backend_schedule .
.Sh HYPERCALL INTERFACES
.Ss Initialization
.Ft int
.Fn rumpuser_init "int version" "struct rump_hyperup *hyp"
.Pp
Initialize the hypervisor.
.Bl -tag -width "xenum_rumpclock"
.It Fa version
hypercall interface version number that the kernel expects to be used.
In case the hypervisor cannot provide an exact match, this routine must
return a non-zero value.
.It Fa hyp
pointer to a set of upcalls the hypervisor can make into the rump kernel
.El
.Ss Memory allocation
.Ft int
.Fn rumpuser_malloc "size_t len" "int alignment" "void **memp"
.Bl -tag -width "xenum_rumpclock"
.It Fa len
amount of memory to allocate
.It Fa alignment
size the returned memory must be aligned to.
For example, if the value passed is 4096, the returned memory
must be aligned to a 4k boundary.
.It Fa memp
return pointer for allocated memory
.El
.Pp
.Ft void
.Fn rumpuser_free "void *mem" "size_t len"
.Bl -tag -width "xenum_rumpclock"
.It Fa mem
memory to free
.It Fa len
length of allocation.
This is always equal to the amount the caller requested from the
.Fn rumpuser_malloc
which returned
.Fa mem .
.El
.Ss Files and I/O
.Ft int
.Fn rumpuser_open "const char *name" "int mode" "int *fdp"
.Pp
Open
.Fa name
for I/O and associate a file descriptor with it.
Notably, there needs to be no mapping between
.Fa name
and the host's file system namespace.
For example, it is possible to associate the file descriptor with
device I/O registers for special values of
.Fa name .
.Bl -tag -width "xenum_rumpclock"
.It Fa name
the identifier of the file to open for I/O
.It Fa mode
combination of the following:
.Bl -tag -width "XRUMPUSER_OPEN_CREATE"
.It Dv RUMPUSER_OPEN_RDONLY
open only for reading
.It Dv RUMPUSER_OPEN_WRONLY
open only for writing
.It Dv RUMPUSER_OPEN_RDWR
open for reading and writing
.It Dv RUMPUSER_OPEN_CREATE
do not treat missing
.Fa name
as an error
.It Dv RUMPUSER_OPEN_EXCL
combined with
.Dv RUMPUSER_OPEN_CREATE ,
flag an error if
.Fa name
already exists
.It Dv RUMPUSER_OPEN_BIO
the caller will use this file for block I/O, usually used in
conjunction with accessing file system media.
The hypervisor should treat this flag as advisory and possibly
enable some optimizations for
.Fa *fdp
based on it.
.El
Notably, the permissions of the created file are left up to the
hypervisor implementation.
.It Fa fdp
An integer value denoting the open file is returned here.
.El
.Pp
.Ft int
.Fn rumpuser_close "int fd"
.Pp
Close a previously opened file descriptor.
.Pp
.Ft int
.Fn rumpuser_getfileinfo "const char *name" "uint64_t *size" "int *type"
.Bl -tag -width "xenum_rumpclock"
.It Fa name
file for which information is returned.
The namespace is equal to that of
.Fn rumpuser_open .
.It Fa size
If
.Pf non- Dv NULL ,
size of the file is returned here.
.It Fa type
If
.Pf non- Dv NULL ,
type of the file is returned here.
The options are
.Dv RUMPUSER_FT_DIR ,
.Dv RUMPUSER_FT_REG ,
.Dv RUMPUSER_FT_BLK ,
.Dv RUMPUSER_FT_CHR ,
or
.Dv RUMPUSER_FT_OTHER
for directory, regular file, block device, character device or unknown,
respectively.
.El
.Pp
.Ft void
.Fo rumpuser_bio
.Fa "int fd" "int op" "void *data" "size_t dlen" "int64_t off"
.Fa "rump_biodone_fn biodone" "void *donearg"
.Fc
.Pp
Initiate block I/O and return immediately.
.Bl -tag -width "xenum_rumpclock"
.It Fa fd
perform I/O on this file descriptor.
The file descriptor must have been opened with
.Dv RUMPUSER_OPEN_BIO .
.It Fa op
Transfer data from the file descriptor with
.Dv RUMPUSER_BIO_READ
and transfer data to the file descriptor with
.Dv RUMPUSER_BIO_WRITE .
Unless
.Dv RUMPUSER_BIO_SYNC
is specified, the hypervisor may cache a write instead of
committing it to permanent storage.
.It Fa data
memory address to transfer data to/from
.It Fa dlen
length of I/O.
The length is guaranteed to be a multiple of 512.
.It Fa off
offset into
.Fa fd
where I/O is performed
.It Fa biodone
To be called when the I/O is complete.
Accessing
.Fa data
is not legal after the call is made.
.It Fa donearg
opaque arg that must be passed to
.Fa biodone .
.El
.Pp
.Ft int
.Fo rumpuser_iovread
.Fa "int fd" "struct rumpuser_iovec *ruiov" "size_t iovlen"
.Fa "int64_t off" "size_t *retv"
.Fc
.Pp
.Ft int
.Fo rumpuser_iovwrite
.Fa "int fd" "struct rumpuser_iovec *ruiov" "size_t iovlen"
.Fa "int64_t off" "size_t *retv"
.Fc
.Pp
These routines perform scatter-gather I/O which is not
block I/O by nature and therefore cannot be handled by
.Fn rumpuser_bio .
.Bl -tag -width "xenum_rumpclock"
.It Fa fd
file descriptor to perform I/O on
.It Fa ruiov
an array of I/O descriptors.
It is defined as follows:
.Bd -literal -offset indent -compact
struct rumpuser_iovec {
	void *iov_base;
	size_t iov_len;
};
.Ed
.It Fa iovlen
number of elements in
.Fa ruiov
.It Fa off
offset of
.Fa fd
to perform I/O on.
This can either be a non-negative value or
.Dv RUMPUSER_IOV_NOSEEK .
The latter denotes that no attempt to change the underlying objects
offset should be made.
Using both types of offsets on a single instance of
.Fa fd
results in undefined behavior.
.It Fa retv
number of bytes successfully transferred is returned here
.El
.Pp
.Ft int
.Fo rumpuser_syncfd
.Fa "int fd" "int flags" "uint64_t start" "uint64_t len"
.Fc
.Pp
Synchronizes
.Fa fd
with respect to backing storage.
The other arguments are:
.Bl -tag -width "xenum_rumpclock"
.It Fa flags
controls how synchronization happens.
It must contain one of the following:
.Bl -tag -width "XRUMPUSER_SYNCFD_BARRIER"
.It Dv RUMPUSER_SYNCFD_READ
Make sure that the next read sees writes from all other parties.
This is useful for example in the case that
.Fa fd
represents memory to write a DMA read is being performed.
.It Dv RUMPUSER_SYNCFD_WRITE
Flush cached writes.
.El
.Pp
The following additional parameters may be passed in
.Fa flags :
.Bl -tag -width "XRUMPUSER_SYNCFD_BARRIER"
.It Dv RUMPUSER_SYNCFD_BARRIER
Issue a barrier.
Outstanding I/O operations which were started before the barrier
complete before any operations after the barrier are performed.
.It Dv RUMPUSER_SYNCFD_SYNC
Wait for the synchronization operation to fully complete before
returning.
For example, this could mean that the data to be written to a disk
has hit either the disk or non-volatile memory.
.El
.It Fa start
offset into the object.
.It Fa len
the number of bytes to synchronize.
The value 0 denotes until the end of the object.
.El
.Ss Clocks
The hypervisor should support two clocks, one for wall time and one
for monotonically increasing time, the latter of which may be based
on some arbitrary time (e.g. system boot time).
If this is not possible, the hypervisor must make a reasonable effort to
retain semantics.
.Pp
.Ft int
.Fn rumpuser_clock_gettime "int enum_rumpclock" "int64_t *sec" "long *nsec"
.Bl -tag -width "xenum_rumpclock"
.It Fa enum_rumpclock
specifies the clock type.
In case of
.Dv RUMPUSER_CLOCK_RELWALL
the wall time should be returned.
In case of
.Dv RUMPUSER_CLOCK_ABSMONO
the time of a monotonic clock should be returned.
.It Fa sec
return value for seconds
.It Fa nsec
return value for nanoseconds
.El
.Pp
.Ft int
.Fn rumpuser_clock_sleep "int enum_rumpclock" "int64_t sec" "long nsec"
.Bl -tag -width "xenum_rumpclock"
.It Fa enum_rumpclock
In case of
.Dv RUMPUSER_CLOCK_RELWALL ,
the sleep should last at least as long as specified.
In case of
.Dv RUMPUSER_CLOCK_ABSMONO ,
the sleep should last until the hypervisor monotonic clock hits
the specified absolute time.
.It Fa sec
sleep duration, seconds.
exact semantics depend on
.Fa clk .
.It Fa nsec
sleep duration, nanoseconds.
exact semantics depend on
.Fa clk .
.El
.Ss Parameter retrieval
.Ft int
.Fn rumpuser_getparam "const char *name" "void *buf" "size_t buflen"
.Pp
Retrieve a configuration parameter from the hypervisor.
It is up to the hypervisor to decide how the parameters can be set.
.Bl -tag -width "xenum_rumpclock"
.It Fa name
name of the parameter.
If the name starts with an underscore, it means a mandatory parameter.
The mandatory parameters are
.Dv RUMPUSER_PARAM_NCPU
which specifies the amount of virtual CPUs bootstrapped by the
rump kernel and
.Dv RUMPUSER_PARAM_HOSTNAME
which returns a preferably unique instance name for the rump kernel.
.It Fa buf
buffer to return the data in as a string
.It Fa buflen
length of buffer
.El
.Ss Termination
.Ft void
.Fn rumpuser_exit "int value"
.Pp
Terminate the rump kernel with exit value
.Fa value .
If
.Fa value
is
.Dv RUMPUSER_PANIC
the hypervisor should attempt to provide something akin to a core dump.
.Ss Console output
Console output is divided into two routines: a per-character
one and printf-like one.
The former is used e.g. by the rump kernel's internal printf
routine.
The latter can be used for direct debug prints e.g. very early
on in the rump kernel's bootstrap or when using the in-kernel
routine causes too much skew in the debug print results
(the hypercall runs outside of the rump kernel and therefore does not
cause any locking or scheduling events inside the rump kernel).
.Pp
.Ft void
.Fn rumpuser_putchar "int ch"
.Pp
Output
.Fa ch
on the console.
.Pp
.Ft void
.Fn rumpuser_dprintf "const char *fmt" "..."
.Pp
Do output based on printf-like parameters.
.Ss Signals
A rump kernel should be able to send signals to client programs
due to some standard interfaces including signal delivery in their
specifications.
Examples of these interfaces include
.Xr setitimer 2
and
.Xr write 2 .
The
.Fn rumpuser_kill
function advises the hypercall implementation to raise a signal for the
process containing the rump kernel.
.Pp
.Ft int
.Fn rumpuser_kill "int64_t pid" "int sig"
.Bl -tag -width "xenum_rumpclock"
.It Fa pid
The pid of the rump kernel process that the signal is directed to.
This value may be used as the hypervisor as a hint on how to deliver
the signal.
The value
.Dv RUMPUSER_PID_SELF
may also be specified to indicate no hint.
This value will be removed in a future version of the hypercall interface.
.It Fa sig
Number of signal to raise.
The value is in
.Nx
signal number namespace.
In case the host has a native representation for signals, the
value should be translated before the signal is raised.
In case there is no mapping between
.Fa sig
and native signals (if any), the behavior is implementation-defined.
.El
.Pp
A rump kernel will ignore the return value of this hypercall.
The only implication of not implementing
.Fn rumpuser_kill
is that some application programs may not experience expected behavior
for standard interfaces.
.Pp
As an aside,the
.Xr rump_sp 7
protocol provides equivalent functionality for remote clients.
.Ss Random pool
.Ft int
.Fn rumpuser_getrandom "void *buf" "size_t buflen" "int flags" "size_t *retp"
.Bl -tag -width "xenum_rumpclock"
.It Fa buf
buffer that the randomness is written to
.It Fa buflen
number of bytes of randomness requested
.It Fa flags
The value 0 or a combination of
.Dv RUMPUSER_RANDOM_HARD
(return true randomness instead of something from a PRNG)
and
.Dv RUMPUSER_RANDOM_NOWAIT
(do not block in case the requested amount of bytes is not available).
.It Fa retp
The number of random bytes written into
.Fa buf .
.El
.Ss Threads
.Ft int
.Fo rumpuser_thread_create
.Fa "void *(*fun)(void *)" "void *arg" "const char *thrname" "int mustjoin"
.Fa "int priority" "int cpuidx" "void **cookie"
.Fc
.Pp
Create a schedulable host thread context.
The rump kernel will call this interface when it creates a kernel thread.
The scheduling policy for the new thread is defined by the hypervisor.
In case the hypervisor wants to optimize the scheduling of the
threads, it can perform heuristics on the
.Fa thrname ,
.Fa priority
and
.Fa cpuidx
parameters.
.Bl -tag -width "xenum_rumpclock"
.It Fa fun
function that the new thread must call.
This call will never return.
.It Fa arg
argument to be passed to
.Fa fun
.It Fa thrname
Name of the new thread.
.It Fa mustjoin
If 1, the thread will be waited for by
.Fn rumpuser_thread_join
when the thread exits.
.It Fa priority
The priority that the kernel requested the thread to be created at.
Higher values mean higher priority.
The exact kernel semantics for each value are not available through
this interface.
.It Fa cpuidx
The index of the virtual CPU that the thread is bound to, or \-1
if the thread is not bound.
The mapping between the virtual CPUs and physical CPUs, if any,
is hypervisor implementation specific.
.It Fa cookie
In case
.Fa mustjoin
is set, the value returned in
.Fa cookie
will be passed to
.Fn rumpuser_thread_join .
.El
.Pp
.Ft void
.Fn rumpuser_thread_exit "void"
.Pp
Called when a thread created with
.Fn rumpuser_thread_create
exits.
.Pp
.Ft int
.Fn rumpuser_thread_join "void *cookie"
.Pp
Wait for a joinable thread to exit.
The cookie matches the value from
.Fn rumpuser_thread_create .
.Pp
.Ft void
.Fn rumpuser_curlwpop "int enum_rumplwpop" "struct lwp *l"
.Pp
Manipulate the hypervisor's thread context database.
The possible operations are create, destroy, and set as specified by
.Fa enum_rumplwpop :
.Bl -tag -width "XRUMPUSER_LWP_DESTROY"
.It Dv RUMPUSER_LWP_CREATE
Inform the hypervisor that
.Fa l
is now a valid thread context which may be set.
A currently valid value of
.Fa l
may not be specified.
This operation is informational and does not mandate any action
from the hypervisor.
.It Dv RUMPUSER_LWP_DESTROY
Inform the hypervisor that
.Fa l
is no longer a valid thread context.
This means that it may no longer be set as the current context.
A currently set context or an invalid one may not be destroyed.
This operation is informational and does not mandate any action
from the hypervisor.
.It Dv RUMPUSER_LWP_SET
Set
.Fa l
as the current host thread's rump kernel context.
A previous context must not exist.
.It Dv RUMPUSER_LWP_CLEAR
Clear the context previous set by
.Dv RUMPUSER_LWP_SET .
The value passed in
.Fa l
is the current thread and is never
.Dv NULL .
.El
.Pp
.Ft struct lwp *
.Fn rumpuser_curlwp "void"
.Pp
Retrieve the rump kernel thread context associated with the current host
thread, as set by
.Fn rumpuser_curlwpop .
This routine may be called when a context is not set and
the routine must return
.Dv NULL
in that case.
This interface is expected to be called very often.
Any optimizations pertaining to the execution speed of this routine
should be done in
.Fn rumpuser_curlwpop .
.Pp
.Ft void
.Fn rumpuser_seterrno "int errno"
.Pp
Set an errno value in the calling thread's TLS.
Note: this is used only if rump kernel clients make rump system calls.
.Ss Mutexes, rwlocks and condition variables
The locking interfaces have standard semantics, so we will not
discuss each one in detail.
The data types
.Vt struct rumpuser_mtx ,
.Vt struct rumpuser_rw
and
.Vt struct rumpuser_cv
used by these interfaces are opaque to the rump kernel, i.e. the
hypervisor has complete freedom over them.
.Pp
Most of these interfaces will (and must) relinquish the rump kernel
CPU context in case they block (or intend to block).
The exceptions are the "nowrap" variants of the interfaces which
may not relinquish rump kernel context.
.Pp
.Ft void
.Fn rumpuser_mutex_init "struct rumpuser_mtx **mtxp" "int flags"
.Pp
.Ft void
.Fn rumpuser_mutex_enter "struct rumpuser_mtx *mtx"
.Pp
.Ft void
.Fn rumpuser_mutex_enter_nowrap "struct rumpuser_mtx *mtx"
.Pp
.Ft int
.Fn rumpuser_mutex_tryenter "struct rumpuser_mtx *mtx"
.Pp
.Ft void
.Fn rumpuser_mutex_exit "struct rumpuser_mtx *mtx"
.Pp
.Ft void
.Fn rumpuser_mutex_destroy "struct rumpuser_mtx *mtx"
.Pp
.Ft void
.Fn rumpuser_mutex_owner "struct rumpuser_mtx *mtx" "struct lwp **lp"
.Pp
Mutexes provide mutually exclusive locking.
The flags, of which at least one must be given, are as follows:
.Bl -tag -width "XRUMPUSER_MTX_KMUTEX"
.It Dv RUMPUSER_MTX_SPIN
Create a spin mutex.
Locking this type of mutex must not relinquish rump kernel context
even when
.Fn rumpuser_mutex_enter
is used.
.It Dv RUMPUSER_MTX_KMUTEX
The mutex must track and be able to return the rump kernel thread
that owns the mutex (if any).
If this flag is not specified,
.Fn rumpuser_mutex_owner
will never be called for that particular mutex.
.El
.Pp
.Ft void
.Fn rumpuser_rw_init "struct rumpuser_rw **rwp"
.Pp
.Ft void
.Fn rumpuser_rw_enter "int enum_rumprwlock" "struct rumpuser_rw *rw"
.Pp
.Ft int
.Fn rumpuser_rw_tryenter "int enum_rumprwlock" "struct rumpuser_rw *rw"
.Pp
.Ft int
.Fn rumpuser_rw_tryupgrade "struct rumpuser_rw *rw"
.Pp
.Ft void
.Fn rumpuser_rw_downgrade "struct rumpuser_rw *rw"
.Pp
.Ft void
.Fn rumpuser_rw_exit "struct rumpuser_rw *rw"
.Pp
.Ft void
.Fn rumpuser_rw_destroy "struct rumpuser_rw *rw"
.Pp
.Ft void
.Fo rumpuser_rw_held
.Fa "int enum_rumprwlock" "struct rumpuser_rw *rw" "int *heldp"
.Fc
.Pp
Read/write locks provide either shared or exclusive locking.
The possible values for
.Fa lk
are
.Dv RUMPUSER_RW_READER
and
.Dv RUMPUSER_RW_WRITER .
Upgrading means trying to migrate from an already owned shared
lock to an exclusive lock and downgrading means migrating from
an already owned exclusive lock to a shared lock.
.Pp
.Ft void
.Fn rumpuser_cv_init "struct rumpuser_cv **cvp"
.Pp
.Ft void
.Fn rumpuser_cv_destroy "struct rumpuser_cv *cv"
.Pp
.Ft void
.Fn rumpuser_cv_wait "struct rumpuser_cv *cv" "struct rumpuser_mtx *mtx"
.Pp
.Ft void
.Fn rumpuser_cv_wait_nowrap "struct rumpuser_cv *cv" "struct rumpuser_mtx *mtx"
.Pp
.Ft int
.Fo rumpuser_cv_timedwait
.Fa "struct rumpuser_cv *cv" "struct rumpuser_mtx *mtx"
.Fa "int64_t sec" "int64_t nsec"
.Fc
.Pp
.Ft void
.Fn rumpuser_cv_signal "struct rumpuser_cv *cv"
.Pp
.Ft void
.Fn rumpuser_cv_broadcast "struct rumpuser_cv *cv"
.Pp
.Ft void
.Fn rumpuser_cv_has_waiters "struct rumpuser_cv *cv" "int *waitersp"
.Pp
Condition variables wait for an event.
The
.Fa mtx
interlock eliminates a race between checking the predicate and
sleeping on the condition variable; the mutex should be released
for the duration of the sleep in the normal atomic manner.
The timedwait variant takes a specifier indicating a relative
sleep duration after which the routine will return with
.Er ETIMEDOUT .
If a timedwait is signaled before the timeout expires, the
routine will return 0.
.Pp
The order in which the hypervisor
reacquires the rump kernel context and interlock mutex before
returning into the rump kernel is as follows.
In case the interlock mutex was initialized with both
.Dv RUMPUSER_MTX_SPIN
and
.Dv RUMPUSER_MTX_KMUTEX ,
the rump kernel context is scheduled before the mutex is reacquired.
In case of a purely
.Dv RUMPUSER_MTX_SPIN
mutex, the mutex is acquired first.
In the final case the order is implementation-defined.
.Sh RETURN VALUES
All routines which return an integer return an errno value.
The hypervisor must translate the value to the native errno
namespace used by the rump kernel.
Routines which do not return an integer may never fail.
.Sh SEE ALSO
.Xr rump 3
.Rs
.%A Antti Kantee
.%D 2012
.%J Aalto University Doctoral Dissertations
.%T Flexible Operating System Internals: The Design and Implementation of the Anykernel and Rump Kernels
.%O Section 2.3.2: The Hypercall Interface
.Re
.Pp
For a list of all known implementations of the
.Nm
interface, see
.Lk http://wiki.rumpkernel.org/Platforms .
.Sh HISTORY
The rump kernel hypercall API was first introduced in
.Nx 5.0 .
The API described above first appeared in
.Nx 7.0 .