1 // Copyright 2016 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 //! Type-safe bindings for Zircon kernel
6 //! [syscalls](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls.md).
8 extern crate fuchsia_zircon_sys
as zircon_sys
;
11 use std
::marker
::PhantomData
;
13 macro_rules
! impl_handle_based
{
14 ($type_name
:path
) => {
15 impl AsHandleRef
for $type_name
{
16 fn as_handle_ref(&self) -> HandleRef
{
17 self.0.as_handle_ref()
21 impl From
<Handle
> for $type_name
{
22 fn from(handle
: Handle
) -> Self {
27 impl From
<$type_name
> for Handle
{
28 fn from(x
: $type_name
) -> Handle
{
33 impl HandleBased
for $type_name {}
49 pub use channel
::{Channel, ChannelOpts, MessageBuf}
;
50 pub use event
::{Event, EventOpts}
;
51 pub use eventpair
::{EventPair, EventPairOpts}
;
52 pub use fifo
::{Fifo, FifoOpts}
;
54 pub use port
::{Packet, PacketContents, Port, PortOpts, SignalPacket, UserPacket, WaitAsyncOpts}
;
55 pub use process
::Process
;
56 pub use socket
::{Socket, SocketOpts, SocketReadOpts, SocketWriteOpts}
;
57 pub use timer
::{Timer, TimerOpts}
;
58 pub use thread
::Thread
;
59 pub use vmo
::{Vmo, VmoCloneOpts, VmoOp, VmoOpts}
;
61 use zircon_sys
as sys
;
63 type Duration
= sys
::zx_duration_t
;
64 type Time
= sys
::zx_time_t
;
65 pub use zircon_sys
::ZX_TIME_INFINITE
;
67 // A placeholder value used for handles that have been taken from the message buf.
68 // We rely on the kernel never to produce any actual handles with this value.
69 const INVALID_HANDLE
: sys
::zx_handle_t
= 0;
71 /// A status code returned from the Zircon kernel.
74 /// [errors.md](https://fuchsia.googlesource.com/zircon/+/master/docs/errors.md)
75 /// in the Zircon documentation for more information about the meaning of these
77 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
79 // Auto-generated using tools/gen_status.py
87 ErrInterruptedRetry
= -6,
93 ErrBufferTooSmall
= -15,
100 ErrAlreadyExists
= -26,
101 ErrAlreadyBound
= -27,
102 ErrUnavailable
= -28,
103 ErrAccessDenied
= -30,
106 ErrIoDataIntegrity
= -42,
116 /// Any zx_status_t not in the set above will map to the following:
117 UnknownOther
= -32768,
119 // used to prevent exhaustive matching
121 __Nonexhaustive
= -32787,
125 pub fn from_raw(raw
: sys
::zx_status_t
) -> Self {
127 // Auto-generated using tools/gen_status.py
128 sys
::ZX_OK
=> Status
::NoError
,
129 sys
::ZX_ERR_INTERNAL
=> Status
::ErrInternal
,
130 sys
::ZX_ERR_NOT_SUPPORTED
=> Status
::ErrNotSupported
,
131 sys
::ZX_ERR_NO_RESOURCES
=> Status
::ErrNoResources
,
132 sys
::ZX_ERR_NO_MEMORY
=> Status
::ErrNoMemory
,
133 sys
::ZX_ERR_CALL_FAILED
=> Status
::ErrCallFailed
,
134 sys
::ZX_ERR_INTERRUPTED_RETRY
=> Status
::ErrInterruptedRetry
,
135 sys
::ZX_ERR_INVALID_ARGS
=> Status
::ErrInvalidArgs
,
136 sys
::ZX_ERR_BAD_HANDLE
=> Status
::ErrBadHandle
,
137 sys
::ZX_ERR_WRONG_TYPE
=> Status
::ErrWrongType
,
138 sys
::ZX_ERR_BAD_SYSCALL
=> Status
::ErrBadSyscall
,
139 sys
::ZX_ERR_OUT_OF_RANGE
=> Status
::ErrOutOfRange
,
140 sys
::ZX_ERR_BUFFER_TOO_SMALL
=> Status
::ErrBufferTooSmall
,
141 sys
::ZX_ERR_BAD_STATE
=> Status
::ErrBadState
,
142 sys
::ZX_ERR_TIMED_OUT
=> Status
::ErrTimedOut
,
143 sys
::ZX_ERR_SHOULD_WAIT
=> Status
::ErrShouldWait
,
144 sys
::ZX_ERR_CANCELED
=> Status
::ErrCanceled
,
145 sys
::ZX_ERR_PEER_CLOSED
=> Status
::ErrPeerClosed
,
146 sys
::ZX_ERR_NOT_FOUND
=> Status
::ErrNotFound
,
147 sys
::ZX_ERR_ALREADY_EXISTS
=> Status
::ErrAlreadyExists
,
148 sys
::ZX_ERR_ALREADY_BOUND
=> Status
::ErrAlreadyBound
,
149 sys
::ZX_ERR_UNAVAILABLE
=> Status
::ErrUnavailable
,
150 sys
::ZX_ERR_ACCESS_DENIED
=> Status
::ErrAccessDenied
,
151 sys
::ZX_ERR_IO
=> Status
::ErrIo
,
152 sys
::ZX_ERR_IO_REFUSED
=> Status
::ErrIoRefused
,
153 sys
::ZX_ERR_IO_DATA_INTEGRITY
=> Status
::ErrIoDataIntegrity
,
154 sys
::ZX_ERR_IO_DATA_LOSS
=> Status
::ErrIoDataLoss
,
155 sys
::ZX_ERR_BAD_PATH
=> Status
::ErrBadPath
,
156 sys
::ZX_ERR_NOT_DIR
=> Status
::ErrNotDir
,
157 sys
::ZX_ERR_NOT_FILE
=> Status
::ErrNotFile
,
158 sys
::ZX_ERR_FILE_BIG
=> Status
::ErrFileBig
,
159 sys
::ZX_ERR_NO_SPACE
=> Status
::ErrNoSpace
,
160 sys
::ZX_ERR_STOP
=> Status
::ErrStop
,
161 sys
::ZX_ERR_NEXT
=> Status
::ErrNext
,
162 _
=> Status
::UnknownOther
,
166 pub fn into_io_err(self) -> io
::Error
{
170 // Note: no to_raw, even though it's easy to implement, partly because
171 // handling of UnknownOther would be tricky.
174 impl From
<io
::ErrorKind
> for Status
{
175 fn from(kind
: io
::ErrorKind
) -> Self {
176 use io
::ErrorKind
::*;
180 NotFound
=> ErrNotFound
,
181 PermissionDenied
=> ErrAccessDenied
,
182 ConnectionRefused
=> ErrIoRefused
,
183 ConnectionAborted
=> ErrPeerClosed
,
184 AddrInUse
=> ErrAlreadyBound
,
185 AddrNotAvailable
=> ErrUnavailable
,
186 BrokenPipe
=> ErrPeerClosed
,
187 AlreadyExists
=> ErrAlreadyExists
,
188 WouldBlock
=> ErrShouldWait
,
189 InvalidInput
=> ErrInvalidArgs
,
190 TimedOut
=> ErrTimedOut
,
191 Interrupted
=> ErrInterruptedRetry
,
202 impl From
<Status
> for io
::ErrorKind
{
203 fn from(status
: Status
) -> io
::ErrorKind
{
204 use io
::ErrorKind
::*;
208 ErrInterruptedRetry
=> Interrupted
,
209 ErrBadHandle
=> BrokenPipe
,
210 ErrTimedOut
=> TimedOut
,
211 ErrShouldWait
=> WouldBlock
,
212 ErrPeerClosed
=> ConnectionAborted
,
213 ErrNotFound
=> NotFound
,
214 ErrAlreadyExists
=> AlreadyExists
,
215 ErrAlreadyBound
=> AlreadyExists
,
216 ErrUnavailable
=> AddrNotAvailable
,
217 ErrAccessDenied
=> PermissionDenied
,
218 ErrIoRefused
=> ConnectionRefused
,
219 ErrIoDataIntegrity
=> InvalidData
,
224 ErrWrongType
=> InvalidInput
,
226 Status
::__Nonexhaustive
|
245 ErrCallFailed
=> Other
,
250 impl From
<io
::Error
> for Status
{
251 fn from(err
: io
::Error
) -> Status
{
256 impl From
<Status
> for io
::Error
{
257 fn from(status
: Status
) -> io
::Error
{
258 io
::Error
::from(io
::ErrorKind
::from(status
))
262 /// Rights associated with a handle.
264 /// See [rights.md](https://fuchsia.googlesource.com/zircon/+/master/docs/rights.md)
265 /// for more information.
266 pub type Rights
= sys
::zx_rights_t
;
267 pub use zircon_sys
::{
275 ZX_RIGHT_GET_PROPERTY
,
276 ZX_RIGHT_SET_PROPERTY
,
278 ZX_RIGHT_SAME_RIGHTS
,
281 /// Signals that can be waited upon.
284 /// [Objects and signals](https://fuchsia.googlesource.com/zircon/+/master/docs/concepts.md#Objects-and-Signals)
285 /// in the Zircon kernel documentation. Note: the names of signals are still in flux.
286 pub type Signals
= sys
::zx_signals_t
;
288 pub use zircon_sys
::{
291 ZX_SIGNAL_HANDLE_CLOSED
,
292 ZX_SIGNAL_LAST_HANDLE
,
310 // Task signals (process, thread, job)
316 ZX_CHANNEL_PEER_CLOSED
,
321 ZX_SOCKET_PEER_CLOSED
,
327 /// A "wait item" containing a handle reference and information about what signals
328 /// to wait on, and, on return from `object_wait_many`, which are pending.
331 pub struct WaitItem
<'a
> {
332 /// The handle to wait on.
333 pub handle
: HandleRef
<'a
>,
334 /// A set of signals to wait for.
335 pub waitfor
: Signals
,
336 /// The set of signals pending, on return of `object_wait_many`.
337 pub pending
: Signals
,
341 /// An identifier to select a particular clock. See
342 /// [zx_time_get](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/time_get.md)
343 /// for more information about the possible values.
345 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
347 /// The number of nanoseconds since the system was powered on. Corresponds to
348 /// `ZX_CLOCK_MONOTONIC`.
350 /// The number of wall clock nanoseconds since the Unix epoch (midnight on January 1 1970) in
351 /// UTC. Corresponds to ZX_CLOCK_UTC.
353 /// The number of nanoseconds the current thread has been running for. Corresponds to
358 /// Get the current time, from the specific clock id.
361 /// [zx_time_get](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/time_get.md)
363 pub fn time_get(clock_id
: ClockId
) -> Time
{
364 unsafe { sys::zx_time_get(clock_id as u32) }
367 /// Read the number of high-precision timer ticks since boot. These ticks may be processor cycles,
368 /// high speed timer, profiling timer, etc. They are not guaranteed to continue advancing when the
369 /// system is asleep.
372 /// [zx_ticks_get](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/ticks_get.md)
374 pub fn ticks_get() -> u64 {
375 unsafe { sys::zx_ticks_get() }
378 /// Compute a deadline for the time in the future that is the given `Duration` away.
381 /// [zx_deadline_after](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/deadline_after.md)
383 pub fn deadline_after(nanos
: Duration
) -> Time
{
384 unsafe { sys::zx_deadline_after(nanos) }
387 /// Sleep until the given deadline.
390 /// [zx_nanosleep](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/nanosleep.md)
392 pub fn nanosleep(deadline
: Time
) {
393 unsafe { sys::zx_nanosleep(deadline); }
396 /// Return the number of high-precision timer ticks in a second.
399 /// [zx_ticks_per_second](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/ticks_per_second.md)
401 pub fn ticks_per_second() -> u64 {
402 unsafe { sys::zx_ticks_per_second() }
405 pub use zircon_sys
::{
406 ZX_CPRNG_DRAW_MAX_LEN
,
407 ZX_CPRNG_ADD_ENTROPY_MAX_LEN
,
410 /// Draw random bytes from the kernel's CPRNG to fill the given buffer. Returns the actual number of
411 /// bytes drawn, which may sometimes be less than the size of the buffer provided.
413 /// The buffer must have length less than `ZX_CPRNG_DRAW_MAX_LEN`.
416 /// [zx_cprng_draw](https://fuchsia.googlesource.com/zircon/+/HEAD/docs/syscalls/cprng_draw.md)
418 pub fn cprng_draw(buffer
: &mut [u8]) -> Result
<usize, Status
> {
420 let status
= unsafe { sys::zx_cprng_draw(buffer.as_mut_ptr(), buffer.len(), &mut actual) }
;
421 into_result(status
, || actual
)
424 /// Mix the given entropy into the kernel CPRNG.
426 /// The buffer must have length less than `ZX_CPRNG_ADD_ENTROPY_MAX_LEN`.
429 /// [zx_cprng_add_entropy](https://fuchsia.googlesource.com/zircon/+/HEAD/docs/syscalls/cprng_add_entropy.md)
431 pub fn cprng_add_entropy(buffer
: &[u8]) -> Result
<(), Status
> {
432 let status
= unsafe { sys::zx_cprng_add_entropy(buffer.as_ptr(), buffer.len()) }
;
433 into_result(status
, || ())
436 fn into_result
<T
, F
>(status
: sys
::zx_status_t
, f
: F
) -> Result
<T
, Status
>
437 where F
: FnOnce() -> T
{
438 // All non-negative values are assumed successful. Note: calls that don't try
439 // to multiplex success values into status return could be more strict here.
443 Err(Status
::from_raw(status
))
449 /// A borrowed reference to a `Handle`.
451 /// Mostly useful as part of a `WaitItem`.
452 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
453 pub struct HandleRef
<'a
> {
454 handle
: sys
::zx_handle_t
,
455 phantom
: PhantomData
<&'a sys
::zx_handle_t
>,
458 impl<'a
> HandleRef
<'a
> {
459 pub fn raw_handle(&self) -> sys
::zx_handle_t
{
463 pub fn duplicate(&self, rights
: Rights
) -> Result
<Handle
, Status
> {
464 let handle
= self.handle
;
466 let status
= unsafe { sys::zx_handle_duplicate(handle, rights, &mut out) }
;
467 into_result(status
, || Handle(out
))
470 pub fn signal(&self, clear_mask
: Signals
, set_mask
: Signals
) -> Result
<(), Status
> {
471 let handle
= self.handle
;
472 let status
= unsafe { sys::zx_object_signal(handle, clear_mask.bits(), set_mask.bits()) }
;
473 into_result(status
, || ())
476 pub fn wait(&self, signals
: Signals
, deadline
: Time
) -> Result
<Signals
, Status
> {
477 let handle
= self.handle
;
478 let mut pending
= sys
::zx_signals_t
::empty();
479 let status
= unsafe {
480 sys
::zx_object_wait_one(handle
, signals
, deadline
, &mut pending
)
482 into_result(status
, || pending
)
485 pub fn wait_async(&self, port
: &Port
, key
: u64, signals
: Signals
, options
: WaitAsyncOpts
)
486 -> Result
<(), Status
>
488 let handle
= self.handle
;
489 let status
= unsafe {
490 sys
::zx_object_wait_async(handle
, port
.raw_handle(), key
, signals
, options
as u32)
492 into_result(status
, || ())
496 /// A trait to get a reference to the underlying handle of an object.
497 pub trait AsHandleRef
{
498 /// Get a reference to the handle. One important use of such a reference is
499 /// for `object_wait_many`.
500 fn as_handle_ref(&self) -> HandleRef
;
502 /// Interpret the reference as a raw handle (an integer type). Two distinct
503 /// handles will have different raw values (so it can perhaps be used as a
504 /// key in a data structure).
505 fn raw_handle(&self) -> sys
::zx_handle_t
{
506 self.as_handle_ref().raw_handle()
509 /// Set and clear userspace-accessible signal bits on an object. Wraps the
510 /// [zx_object_signal](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_signal.md)
512 fn signal_handle(&self, clear_mask
: Signals
, set_mask
: Signals
) -> Result
<(), Status
> {
513 self.as_handle_ref().signal(clear_mask
, set_mask
)
516 /// Waits on a handle. Wraps the
517 /// [zx_object_wait_one](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_wait_one.md)
519 fn wait_handle(&self, signals
: Signals
, deadline
: Time
) -> Result
<Signals
, Status
> {
520 self.as_handle_ref().wait(signals
, deadline
)
523 /// Causes packet delivery on the given port when the object changes state and matches signals.
524 /// [zx_object_wait_async](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_wait_async.md)
526 fn wait_async_handle(&self, port
: &Port
, key
: u64, signals
: Signals
, options
: WaitAsyncOpts
)
527 -> Result
<(), Status
>
529 self.as_handle_ref().wait_async(port
, key
, signals
, options
)
533 impl<'a
> AsHandleRef
for HandleRef
<'a
> {
534 fn as_handle_ref(&self) -> HandleRef { *self }
537 /// A trait implemented by all handle-based types.
539 /// Note: it is reasonable for user-defined objects wrapping a handle to implement
540 /// this trait. For example, a specific interface in some protocol might be
541 /// represented as a newtype of `Channel`, and implement the `as_handle_ref`
542 /// method and the `From<Handle>` trait to facilitate conversion from and to the
544 pub trait HandleBased
: AsHandleRef
+ From
<Handle
> + Into
<Handle
> {
545 /// Duplicate a handle, possibly reducing the rights available. Wraps the
546 /// [zx_handle_duplicate](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/handle_duplicate.md)
548 fn duplicate_handle(&self, rights
: Rights
) -> Result
<Self, Status
> {
549 self.as_handle_ref().duplicate(rights
).map(|handle
| Self::from(handle
))
552 /// Create a replacement for a handle, possibly reducing the rights available. This invalidates
553 /// the original handle. Wraps the
554 /// [zx_handle_replace](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/handle_replace.md)
556 fn replace_handle(self, rights
: Rights
) -> Result
<Self, Status
> {
557 <Self as Into
<Handle
>>::into(self)
558 .replace(rights
).map(|handle
| Self::from(handle
))
561 /// Converts the value into its inner handle.
563 /// This is a convenience function which simply forwards to the `Into` trait.
564 fn into_handle(self) -> Handle
{
568 /// Creates an instance of this type from a handle.
570 /// This is a convenience function which simply forwards to the `From` trait.
571 fn from_handle(handle
: Handle
) -> Self {
575 /// Creates an instance of another handle-based type from this value's inner handle.
576 fn into_handle_based
<H
: HandleBased
>(self) -> H
{
577 H
::from_handle(self.into_handle())
580 /// Creates an instance of this type from the inner handle of another
581 /// handle-based type.
582 fn from_handle_based
<H
: HandleBased
>(h
: H
) -> Self {
583 Self::from_handle(h
.into_handle())
587 /// A trait implemented by all handles for objects which have a peer.
588 pub trait Peered
: HandleBased
{
589 /// Set and clear userspace-accessible signal bits on the object's peer. Wraps the
590 /// [zx_object_signal_peer](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_signal.md)
592 fn signal_peer(&self, clear_mask
: Signals
, set_mask
: Signals
) -> Result
<(), Status
> {
593 let handle
= self.as_handle_ref().handle
;
594 let status
= unsafe {
595 sys
::zx_object_signal_peer(handle
, clear_mask
.bits(), set_mask
.bits())
597 into_result(status
, || ())
601 /// A trait implemented by all handles for objects which can have a cookie attached.
602 pub trait Cookied
: HandleBased
{
603 /// Get the cookie attached to this object, if any. Wraps the
604 /// [zx_object_get_cookie](https://fuchsia.googlesource.com/zircon/+/HEAD/docs/syscalls/object_get_cookie.md)
606 fn get_cookie(&self, scope
: &HandleRef
) -> Result
<u64, Status
> {
607 let handle
= self.as_handle_ref().handle
;
609 let status
= unsafe { sys::zx_object_get_cookie(handle, scope.handle, &mut cookie) }
;
610 into_result(status
, || cookie
)
613 /// Attach an opaque cookie to this object with the given scope. The cookie may be read or
614 /// changed in future only with the same scope. Wraps the
615 /// [zx_object_set_cookie](https://fuchsia.googlesource.com/zircon/+/HEAD/docs/syscalls/object_set_cookie.md)
617 fn set_cookie(&self, scope
: &HandleRef
, cookie
: u64) -> Result
<(), Status
> {
618 let handle
= self.as_handle_ref().handle
;
619 let status
= unsafe { sys::zx_object_set_cookie(handle, scope.handle, cookie) }
;
620 into_result(status
, || ())
624 fn handle_drop(handle
: sys
::zx_handle_t
) {
625 let _
= unsafe { sys::zx_handle_close(handle) }
;
628 /// Wait on multiple handles.
629 /// The success return value is a bool indicating whether one or more of the
630 /// provided handle references was closed during the wait.
633 /// [zx_object_wait_many](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_wait_many.md)
635 pub fn object_wait_many(items
: &mut [WaitItem
], deadline
: Time
) -> Result
<bool
, Status
>
637 let len
= try
!(usize_into_u32(items
.len()).map_err(|_
| Status
::ErrOutOfRange
));
638 let items_ptr
= items
.as_mut_ptr() as *mut sys
::zx_wait_item_t
;
639 let status
= unsafe { sys::zx_object_wait_many( items_ptr, len, deadline) }
;
640 if status
== sys
::ZX_ERR_CANCELED
{
643 into_result(status
, || false)
648 /// An object representing a Zircon
649 /// [handle](https://fuchsia.googlesource.com/zircon/+/master/docs/handles.md).
651 /// Internally, it is represented as a 32-bit integer, but this wrapper enforces
652 /// strict ownership semantics. The `Drop` implementation closes the handle.
654 /// This type represents the most general reference to a kernel object, and can
655 /// be interconverted to and from more specific types. Those conversions are not
656 /// enforced in the type system; attempting to use them will result in errors
657 /// returned by the kernel. These conversions don't change the underlying
658 /// representation, but do change the type and thus what operations are available.
659 #[derive(Debug, Eq, PartialEq, Hash)]
660 pub struct Handle(sys
::zx_handle_t
);
662 impl AsHandleRef
for Handle
{
663 fn as_handle_ref(&self) -> HandleRef
{
664 HandleRef { handle: self.0, phantom: Default::default() }
668 impl HandleBased
for Handle {}
670 impl Drop
for Handle
{
677 /// If a raw handle is obtained from some other source, this method converts
678 /// it into a type-safe owned handle.
679 pub unsafe fn from_raw(raw
: sys
::zx_handle_t
) -> Handle
{
683 pub fn replace(self, rights
: Rights
) -> Result
<Handle
, Status
> {
686 let status
= unsafe { sys::zx_handle_replace(handle, rights, &mut out) }
;
687 into_result(status
, || Handle(out
))
696 fn monotonic_time_increases() {
697 let time1
= time_get(ClockId
::Monotonic
);
698 nanosleep(deadline_after(1_000));
699 let time2
= time_get(ClockId
::Monotonic
);
700 assert
!(time2
> time1
);
704 fn utc_time_increases() {
705 let time1
= time_get(ClockId
::UTC
);
706 nanosleep(deadline_after(1_000));
707 let time2
= time_get(ClockId
::UTC
);
708 assert
!(time2
> time1
);
712 fn thread_time_increases() {
713 let time1
= time_get(ClockId
::Thread
);
714 nanosleep(deadline_after(1_000));
715 let time2
= time_get(ClockId
::Thread
);
716 assert
!(time2
> time1
);
720 fn ticks_increases() {
721 let ticks1
= ticks_get();
722 nanosleep(deadline_after(1_000));
723 let ticks2
= ticks_get();
724 assert
!(ticks2
> ticks1
);
729 let sleep_ns
= 1_000_000; // 1ms
730 let one_second_ns
= 1_000_000_000; // 1 second in ns
731 let ticks1
= ticks_get();
732 nanosleep(deadline_after(sleep_ns
));
733 let ticks2
= ticks_get();
734 // The number of ticks should have increased by at least 1 ms worth
735 assert
!(ticks2
> ticks1
+ sleep_ns
* ticks_per_second() / one_second_ns
);
740 let sleep_ns
= 1_000_000; // 1ms
741 let time1
= time_get(ClockId
::Monotonic
);
742 nanosleep(deadline_after(sleep_ns
));
743 let time2
= time_get(ClockId
::Monotonic
);
744 assert
!(time2
> time1
+ sleep_ns
);
747 /// Test duplication by means of a VMO
750 let hello_length
: usize = 5;
752 // Create a VMO and write some data to it.
753 let vmo
= Vmo
::create(hello_length
as u64, VmoOpts
::Default
).unwrap();
754 assert
!(vmo
.write(b
"hello", 0).is_ok());
756 // Replace, reducing rights to read.
757 let readonly_vmo
= vmo
.duplicate_handle(ZX_RIGHT_READ
).unwrap();
758 // Make sure we can read but not write.
759 let mut read_vec
= vec
![0; hello_length
];
760 assert_eq
!(readonly_vmo
.read(&mut read_vec
, 0).unwrap(), hello_length
);
761 assert_eq
!(read_vec
, b
"hello");
762 assert_eq
!(readonly_vmo
.write(b
"", 0), Err(Status
::ErrAccessDenied
));
764 // Write new data to the original handle, and read it from the new handle
765 assert
!(vmo
.write(b
"bye", 0).is_ok());
766 assert_eq
!(readonly_vmo
.read(&mut read_vec
, 0).unwrap(), hello_length
);
767 assert_eq
!(read_vec
, b
"byelo");
770 // Test replace by means of a VMO
773 let hello_length
: usize = 5;
775 // Create a VMO and write some data to it.
776 let vmo
= Vmo
::create(hello_length
as u64, VmoOpts
::Default
).unwrap();
777 assert
!(vmo
.write(b
"hello", 0).is_ok());
779 // Replace, reducing rights to read.
780 let readonly_vmo
= vmo
.replace_handle(ZX_RIGHT_READ
).unwrap();
781 // Make sure we can read but not write.
782 let mut read_vec
= vec
![0; hello_length
];
783 assert_eq
!(readonly_vmo
.read(&mut read_vec
, 0).unwrap(), hello_length
);
784 assert_eq
!(read_vec
, b
"hello");
785 assert_eq
!(readonly_vmo
.write(b
"", 0), Err(Status
::ErrAccessDenied
));
789 fn wait_and_signal() {
790 let event
= Event
::create(EventOpts
::Default
).unwrap();
791 let ten_ms
: Duration
= 10_000_000;
793 // Waiting on it without setting any signal should time out.
794 assert_eq
!(event
.wait_handle(
795 ZX_USER_SIGNAL_0
, deadline_after(ten_ms
)), Err(Status
::ErrTimedOut
));
797 // If we set a signal, we should be able to wait for it.
798 assert
!(event
.signal_handle(ZX_SIGNAL_NONE
, ZX_USER_SIGNAL_0
).is_ok());
799 assert_eq
!(event
.wait_handle(ZX_USER_SIGNAL_0
, deadline_after(ten_ms
)).unwrap(),
800 ZX_USER_SIGNAL_0
| ZX_SIGNAL_LAST_HANDLE
);
802 // Should still work, signals aren't automatically cleared.
803 assert_eq
!(event
.wait_handle(ZX_USER_SIGNAL_0
, deadline_after(ten_ms
)).unwrap(),
804 ZX_USER_SIGNAL_0
| ZX_SIGNAL_LAST_HANDLE
);
806 // Now clear it, and waiting should time out again.
807 assert
!(event
.signal_handle(ZX_USER_SIGNAL_0
, ZX_SIGNAL_NONE
).is_ok());
808 assert_eq
!(event
.wait_handle(
809 ZX_USER_SIGNAL_0
, deadline_after(ten_ms
)), Err(Status
::ErrTimedOut
));
813 fn wait_many_and_signal() {
814 let ten_ms
: Duration
= 10_000_000;
815 let e1
= Event
::create(EventOpts
::Default
).unwrap();
816 let e2
= Event
::create(EventOpts
::Default
).unwrap();
818 // Waiting on them now should time out.
819 let mut items
= vec
![
820 WaitItem { handle: e1.as_handle_ref(), waitfor: ZX_USER_SIGNAL_0, pending: ZX_SIGNAL_NONE }
,
821 WaitItem { handle: e2.as_handle_ref(), waitfor: ZX_USER_SIGNAL_1, pending: ZX_SIGNAL_NONE }
,
823 assert_eq
!(object_wait_many(&mut items
, deadline_after(ten_ms
)), Err(Status
::ErrTimedOut
));
824 assert_eq
!(items
[0].pending
, ZX_SIGNAL_LAST_HANDLE
);
825 assert_eq
!(items
[1].pending
, ZX_SIGNAL_LAST_HANDLE
);
827 // Signal one object and it should return success.
828 assert
!(e1
.signal_handle(ZX_SIGNAL_NONE
, ZX_USER_SIGNAL_0
).is_ok());
829 assert
!(object_wait_many(&mut items
, deadline_after(ten_ms
)).is_ok());
830 assert_eq
!(items
[0].pending
, ZX_USER_SIGNAL_0
| ZX_SIGNAL_LAST_HANDLE
);
831 assert_eq
!(items
[1].pending
, ZX_SIGNAL_LAST_HANDLE
);
833 // Signal the other and it should return both.
834 assert
!(e2
.signal_handle(ZX_SIGNAL_NONE
, ZX_USER_SIGNAL_1
).is_ok());
835 assert
!(object_wait_many(&mut items
, deadline_after(ten_ms
)).is_ok());
836 assert_eq
!(items
[0].pending
, ZX_USER_SIGNAL_0
| ZX_SIGNAL_LAST_HANDLE
);
837 assert_eq
!(items
[1].pending
, ZX_USER_SIGNAL_1
| ZX_SIGNAL_LAST_HANDLE
);
839 // Clear signals on both; now it should time out again.
840 assert
!(e1
.signal_handle(ZX_USER_SIGNAL_0
, ZX_SIGNAL_NONE
).is_ok());
841 assert
!(e2
.signal_handle(ZX_USER_SIGNAL_1
, ZX_SIGNAL_NONE
).is_ok());
842 assert_eq
!(object_wait_many(&mut items
, deadline_after(ten_ms
)), Err(Status
::ErrTimedOut
));
843 assert_eq
!(items
[0].pending
, ZX_SIGNAL_LAST_HANDLE
);
844 assert_eq
!(items
[1].pending
, ZX_SIGNAL_LAST_HANDLE
);
849 let event
= Event
::create(EventOpts
::Default
).unwrap();
850 let scope
= Event
::create(EventOpts
::Default
).unwrap();
852 // Getting a cookie when none has been set should fail.
853 assert_eq
!(event
.get_cookie(&scope
.as_handle_ref()), Err(Status
::ErrAccessDenied
));
856 assert_eq
!(event
.set_cookie(&scope
.as_handle_ref(), 42), Ok(()));
858 // Should get it back....
859 assert_eq
!(event
.get_cookie(&scope
.as_handle_ref()), Ok(42));
861 // but not with the wrong scope!
862 assert_eq
!(event
.get_cookie(&event
.as_handle_ref()), Err(Status
::ErrAccessDenied
));
864 // Can change it, with the same scope...
865 assert_eq
!(event
.set_cookie(&scope
.as_handle_ref(), 123), Ok(()));
867 // but not with a different scope.
868 assert_eq
!(event
.set_cookie(&event
.as_handle_ref(), 123), Err(Status
::ErrAccessDenied
));
873 let mut buffer
= [0; 20];
874 assert_eq
!(cprng_draw(&mut buffer
), Ok(20));
875 assert_ne
!(buffer
[0], 0);
876 assert_ne
!(buffer
[19], 0);
880 fn cprng_too_large() {
881 let mut buffer
= [0; ZX_CPRNG_DRAW_MAX_LEN
+ 1];
882 assert_eq
!(cprng_draw(&mut buffer
), Err(Status
::ErrInvalidArgs
));
884 for mut s
in buffer
.chunks_mut(ZX_CPRNG_DRAW_MAX_LEN
) {
885 assert_eq
!(cprng_draw(&mut s
), Ok(s
.len()));
891 let buffer
= [0, 1, 2];
892 assert_eq
!(cprng_add_entropy(&buffer
), Ok(()));
896 pub fn usize_into_u32(n
: usize) -> Result
<u32, ()> {
897 if n
> ::std
::u32::MAX
as usize || n
< ::std
::u32::MIN
as usize {
903 pub fn size_to_u32_sat(n
: usize) -> u32 {
904 if n
> ::std
::u32::MAX
as usize {
905 return ::std
::u32::MAX
;
907 if n
< ::std
::u32::MIN
as usize {
908 return ::std
::u32::MIN
;