1extern crate core;
9extern crate magenta_sys;
10
11use std::marker::PhantomData;
12
13macro_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()
18 }
19 }
20
21 impl From<Handle> for $type_name {
22 fn from(handle: Handle) -> Self {
23 $type_name(handle)
24 }
25 }
26
27 impl Into<Handle> for $type_name {
28 fn into(self) -> Handle {
29 self.0
30 }
31 }
32
33 impl HandleBased for $type_name {}
34 }
35}
36
37mod channel;
38mod event;
39mod eventpair;
40mod fifo;
41mod job;
42mod port;
43mod process;
44mod socket;
45mod timer;
46mod thread;
47mod vmo;
48
49pub use channel::{Channel, ChannelOpts, MessageBuf};
50pub use event::{Event, EventOpts};
51pub use eventpair::{EventPair, EventPairOpts};
52pub use fifo::{Fifo, FifoOpts};
53pub use job::Job;
54pub use port::{Packet, PacketContents, Port, PortOpts, SignalPacket, UserPacket, WaitAsyncOpts};
55pub use process::Process;
56pub use socket::{Socket, SocketOpts, SocketReadOpts, SocketWriteOpts};
57pub use timer::{Timer, TimerOpts};
58pub use thread::Thread;
59pub use vmo::{Vmo, VmoCloneOpts, VmoOp, VmoOpts};
60
61use magenta_sys as sys;
62
63type Duration = sys::mx_duration_t;
64type Time = sys::mx_time_t;
65pub use magenta_sys::MX_TIME_INFINITE;
66
67const INVALID_HANDLE: sys::mx_handle_t = 0;
70
71#[derive(Debug, PartialEq, Eq, Clone, Copy)]
78#[repr(i32)]
79pub enum Status {
81 NoError = 0,
82 ErrInternal = -1,
83 ErrNotSupported = -2,
84 ErrNoResources = -3,
85 ErrNoMemory = -4,
86 ErrCallFailed = -5,
87 ErrInterruptedRetry = -6,
88 ErrInvalidArgs = -10,
89 ErrBadHandle = -11,
90 ErrWrongType = -12,
91 ErrBadSyscall = -13,
92 ErrOutOfRange = -14,
93 ErrBufferTooSmall = -15,
94 ErrBadState = -20,
95 ErrTimedOut = -21,
96 ErrShouldWait = -22,
97 ErrCanceled = -23,
98 ErrPeerClosed = -24,
99 ErrNotFound = -25,
100 ErrAlreadyExists = -26,
101 ErrAlreadyBound = -27,
102 ErrUnavailable = -28,
103 ErrAccessDenied = -30,
104 ErrIo = -40,
105 ErrIoRefused = -41,
106 ErrIoDataIntegrity = -42,
107 ErrIoDataLoss = -43,
108 ErrBadPath = -50,
109 ErrNotDir = -51,
110 ErrNotFile = -52,
111 ErrFileBig = -53,
112 ErrNoSpace = -54,
113 ErrStop = -60,
114 ErrNext = -61,
115
116 UnknownOther = -32768,
118}
119
120impl Status {
121 pub fn from_raw(raw: sys::mx_status_t) -> Self {
122 match raw {
123 sys::MX_OK => Status::NoError,
125 sys::MX_ERR_INTERNAL => Status::ErrInternal,
126 sys::MX_ERR_NOT_SUPPORTED => Status::ErrNotSupported,
127 sys::MX_ERR_NO_RESOURCES => Status::ErrNoResources,
128 sys::MX_ERR_NO_MEMORY => Status::ErrNoMemory,
129 sys::MX_ERR_CALL_FAILED => Status::ErrCallFailed,
130 sys::MX_ERR_INTERRUPTED_RETRY => Status::ErrInterruptedRetry,
131 sys::MX_ERR_INVALID_ARGS => Status::ErrInvalidArgs,
132 sys::MX_ERR_BAD_HANDLE => Status::ErrBadHandle,
133 sys::MX_ERR_WRONG_TYPE => Status::ErrWrongType,
134 sys::MX_ERR_BAD_SYSCALL => Status::ErrBadSyscall,
135 sys::MX_ERR_OUT_OF_RANGE => Status::ErrOutOfRange,
136 sys::MX_ERR_BUFFER_TOO_SMALL => Status::ErrBufferTooSmall,
137 sys::MX_ERR_BAD_STATE => Status::ErrBadState,
138 sys::MX_ERR_TIMED_OUT => Status::ErrTimedOut,
139 sys::MX_ERR_SHOULD_WAIT => Status::ErrShouldWait,
140 sys::MX_ERR_CANCELED => Status::ErrCanceled,
141 sys::MX_ERR_PEER_CLOSED => Status::ErrPeerClosed,
142 sys::MX_ERR_NOT_FOUND => Status::ErrNotFound,
143 sys::MX_ERR_ALREADY_EXISTS => Status::ErrAlreadyExists,
144 sys::MX_ERR_ALREADY_BOUND => Status::ErrAlreadyBound,
145 sys::MX_ERR_UNAVAILABLE => Status::ErrUnavailable,
146 sys::MX_ERR_ACCESS_DENIED => Status::ErrAccessDenied,
147 sys::MX_ERR_IO => Status::ErrIo,
148 sys::MX_ERR_IO_REFUSED => Status::ErrIoRefused,
149 sys::MX_ERR_IO_DATA_INTEGRITY => Status::ErrIoDataIntegrity,
150 sys::MX_ERR_IO_DATA_LOSS => Status::ErrIoDataLoss,
151 sys::MX_ERR_BAD_PATH => Status::ErrBadPath,
152 sys::MX_ERR_NOT_DIR => Status::ErrNotDir,
153 sys::MX_ERR_NOT_FILE => Status::ErrNotFile,
154 sys::MX_ERR_FILE_BIG => Status::ErrFileBig,
155 sys::MX_ERR_NO_SPACE => Status::ErrNoSpace,
156 sys::MX_ERR_STOP => Status::ErrStop,
157 sys::MX_ERR_NEXT => Status::ErrNext,
158 _ => Status::UnknownOther,
159 }
160 }
161
162 }
165
166pub type Rights = sys::mx_rights_t;
171pub use magenta_sys::{
172 MX_RIGHT_NONE,
173 MX_RIGHT_DUPLICATE,
174 MX_RIGHT_TRANSFER,
175 MX_RIGHT_READ,
176 MX_RIGHT_WRITE,
177 MX_RIGHT_EXECUTE,
178 MX_RIGHT_MAP,
179 MX_RIGHT_GET_PROPERTY,
180 MX_RIGHT_SET_PROPERTY,
181 MX_RIGHT_DEBUG,
182 MX_RIGHT_SAME_RIGHTS,
183};
184
185pub type Signals = sys::mx_signals_t;
191
192pub use magenta_sys::{
193 MX_SIGNAL_NONE,
194
195 MX_SIGNAL_HANDLE_CLOSED,
196 MX_SIGNAL_LAST_HANDLE,
197
198 MX_USER_SIGNAL_0,
199 MX_USER_SIGNAL_1,
200 MX_USER_SIGNAL_2,
201 MX_USER_SIGNAL_3,
202 MX_USER_SIGNAL_4,
203 MX_USER_SIGNAL_5,
204 MX_USER_SIGNAL_6,
205 MX_USER_SIGNAL_7,
206
207 MX_EVENT_SIGNALED,
209
210 MX_EPAIR_SIGNALED,
212 MX_EPAIR_CLOSED,
213
214 MX_TASK_TERMINATED,
216
217 MX_CHANNEL_READABLE,
219 MX_CHANNEL_WRITABLE,
220 MX_CHANNEL_PEER_CLOSED,
221
222 MX_SOCKET_READABLE,
224 MX_SOCKET_WRITABLE,
225 MX_SOCKET_PEER_CLOSED,
226
227 MX_TIMER_SIGNALED,
229};
230
231#[repr(C)]
234#[derive(Debug)]
235pub struct WaitItem<'a> {
236 pub handle: HandleRef<'a>,
238 pub waitfor: Signals,
240 pub pending: Signals,
242}
243
244
245#[repr(u32)]
249#[derive(Debug, Copy, Clone, Eq, PartialEq)]
250pub enum ClockId {
251 Monotonic = 0,
254 UTC = 1,
257 Thread = 2,
260}
261
262pub fn time_get(clock_id: ClockId) -> Time {
268 unsafe { sys::mx_time_get(clock_id as u32) }
269}
270
271pub fn ticks_get() -> u64 {
279 unsafe { sys::mx_ticks_get() }
280}
281
282pub fn deadline_after(nanos: Duration) -> Time {
288 unsafe { sys::mx_deadline_after(nanos) }
289}
290
291pub fn nanosleep(deadline: Time) {
297 unsafe { sys::mx_nanosleep(deadline); }
298}
299
300pub fn ticks_per_second() -> u64 {
306 unsafe { sys::mx_ticks_per_second() }
307}
308
309pub use magenta_sys::{
310 MX_CPRNG_DRAW_MAX_LEN,
311 MX_CPRNG_ADD_ENTROPY_MAX_LEN,
312};
313
314pub fn cprng_draw(buffer: &mut [u8]) -> Result<usize, Status> {
323 let mut actual = 0;
324 let status = unsafe { sys::mx_cprng_draw(buffer.as_mut_ptr(), buffer.len(), &mut actual) };
325 into_result(status, || actual)
326}
327
328pub fn cprng_add_entropy(buffer: &[u8]) -> Result<(), Status> {
336 let status = unsafe { sys::mx_cprng_add_entropy(buffer.as_ptr(), buffer.len()) };
337 into_result(status, || ())
338}
339
340fn into_result<T, F>(status: sys::mx_status_t, f: F) -> Result<T, Status>
341 where F: FnOnce() -> T {
342 if status >= 0 {
345 Ok(f())
346 } else {
347 Err(Status::from_raw(status))
348 }
349}
350
351#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
357pub struct HandleRef<'a> {
358 handle: sys::mx_handle_t,
359 phantom: PhantomData<&'a sys::mx_handle_t>,
360}
361
362impl<'a> HandleRef<'a> {
363 pub fn raw_handle(&self) -> sys::mx_handle_t {
364 self.handle
365 }
366
367 pub fn duplicate(&self, rights: Rights) -> Result<Handle, Status> {
368 let handle = self.handle;
369 let mut out = 0;
370 let status = unsafe { sys::mx_handle_duplicate(handle, rights, &mut out) };
371 into_result(status, || Handle(out))
372 }
373
374 pub fn signal(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
375 let handle = self.handle;
376 let status = unsafe { sys::mx_object_signal(handle, clear_mask.bits(), set_mask.bits()) };
377 into_result(status, || ())
378 }
379
380 pub fn wait(&self, signals: Signals, deadline: Time) -> Result<Signals, Status> {
381 let handle = self.handle;
382 let mut pending = sys::mx_signals_t::empty();
383 let status = unsafe {
384 sys::mx_object_wait_one(handle, signals, deadline, &mut pending)
385 };
386 into_result(status, || pending)
387 }
388
389 pub fn wait_async(&self, port: &Port, key: u64, signals: Signals, options: WaitAsyncOpts)
390 -> Result<(), Status>
391 {
392 let handle = self.handle;
393 let status = unsafe {
394 sys::mx_object_wait_async(handle, port.raw_handle(), key, signals, options as u32)
395 };
396 into_result(status, || ())
397 }
398}
399
400pub trait AsHandleRef {
402 fn as_handle_ref(&self) -> HandleRef;
405
406 fn raw_handle(&self) -> sys::mx_handle_t {
410 self.as_handle_ref().raw_handle()
411 }
412
413 fn signal_handle(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
417 self.as_handle_ref().signal(clear_mask, set_mask)
418 }
419
420 fn wait_handle(&self, signals: Signals, deadline: Time) -> Result<Signals, Status> {
424 self.as_handle_ref().wait(signals, deadline)
425 }
426
427 fn wait_async_handle(&self, port: &Port, key: u64, signals: Signals, options: WaitAsyncOpts)
431 -> Result<(), Status>
432 {
433 self.as_handle_ref().wait_async(port, key, signals, options)
434 }
435}
436
437impl<'a> AsHandleRef for HandleRef<'a> {
438 fn as_handle_ref(&self) -> HandleRef { *self }
439}
440
441pub trait HandleBased: AsHandleRef + From<Handle> + Into<Handle> {
449 fn duplicate_handle(&self, rights: Rights) -> Result<Self, Status> {
453 self.as_handle_ref().duplicate(rights).map(|handle| Self::from(handle))
454 }
455
456 fn replace_handle(self, rights: Rights) -> Result<Self, Status> {
461 <Self as Into<Handle>>::into(self)
462 .replace(rights).map(|handle| Self::from(handle))
463 }
464}
465
466pub trait Peered: HandleBased {
468 fn signal_peer(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
472 let handle = self.as_handle_ref().handle;
473 let status = unsafe {
474 sys::mx_object_signal_peer(handle, clear_mask.bits(), set_mask.bits())
475 };
476 into_result(status, || ())
477 }
478}
479
480pub trait Cookied: HandleBased {
482 fn get_cookie(&self, scope: &HandleRef) -> Result<u64, Status> {
486 let handle = self.as_handle_ref().handle;
487 let mut cookie = 0;
488 let status = unsafe { sys::mx_object_get_cookie(handle, scope.handle, &mut cookie) };
489 into_result(status, || cookie)
490 }
491
492 fn set_cookie(&self, scope: &HandleRef, cookie: u64) -> Result<(), Status> {
497 let handle = self.as_handle_ref().handle;
498 let status = unsafe { sys::mx_object_set_cookie(handle, scope.handle, cookie) };
499 into_result(status, || ())
500 }
501}
502
503fn handle_drop(handle: sys::mx_handle_t) {
504 let _ = unsafe { sys::mx_handle_close(handle) };
505}
506
507pub fn object_wait_many(items: &mut [WaitItem], deadline: Time) -> Result<bool, Status>
515{
516 let len = try!(usize_into_u32(items.len()).map_err(|_| Status::ErrOutOfRange));
517 let items_ptr = items.as_mut_ptr() as *mut sys::mx_wait_item_t;
518 let status = unsafe { sys::mx_object_wait_many( items_ptr, len, deadline) };
519 if status == sys::MX_ERR_CANCELED {
520 return Ok((true))
521 }
522 into_result(status, || false)
523}
524
525#[derive(Debug, Eq, PartialEq, Hash)]
539pub struct Handle(sys::mx_handle_t);
540
541impl AsHandleRef for Handle {
542 fn as_handle_ref(&self) -> HandleRef {
543 HandleRef { handle: self.0, phantom: Default::default() }
544 }
545}
546
547impl HandleBased for Handle {}
548
549impl Drop for Handle {
550 fn drop(&mut self) {
551 handle_drop(self.0)
552 }
553}
554
555impl Handle {
556 pub unsafe fn from_raw(raw: sys::mx_handle_t) -> Handle {
559 Handle(raw)
560 }
561
562 pub fn replace(self, rights: Rights) -> Result<Handle, Status> {
563 let handle = self.0;
564 let mut out = 0;
565 let status = unsafe { sys::mx_handle_replace(handle, rights, &mut out) };
566 into_result(status, || Handle(out))
567 }
568}
569
570#[cfg(test)]
571mod tests {
572 use super::*;
573
574 #[test]
575 fn monotonic_time_increases() {
576 let time1 = time_get(ClockId::Monotonic);
577 nanosleep(deadline_after(1_000));
578 let time2 = time_get(ClockId::Monotonic);
579 assert!(time2 > time1);
580 }
581
582 #[test]
583 fn utc_time_increases() {
584 let time1 = time_get(ClockId::UTC);
585 nanosleep(deadline_after(1_000));
586 let time2 = time_get(ClockId::UTC);
587 assert!(time2 > time1);
588 }
589
590 #[test]
591 fn thread_time_increases() {
592 let time1 = time_get(ClockId::Thread);
593 nanosleep(deadline_after(1_000));
594 let time2 = time_get(ClockId::Thread);
595 assert!(time2 > time1);
596 }
597
598 #[test]
599 fn ticks_increases() {
600 let ticks1 = ticks_get();
601 nanosleep(deadline_after(1_000));
602 let ticks2 = ticks_get();
603 assert!(ticks2 > ticks1);
604 }
605
606 #[test]
607 fn tick_length() {
608 let sleep_ns = 1_000_000; let one_second_ns = 1_000_000_000; let ticks1 = ticks_get();
611 nanosleep(deadline_after(sleep_ns));
612 let ticks2 = ticks_get();
613 assert!(ticks2 > ticks1 + sleep_ns * ticks_per_second() / one_second_ns);
615 assert!(ticks2 < ticks1 + 4 * sleep_ns * ticks_per_second() / one_second_ns);
617 }
618
619 #[test]
620 fn sleep() {
621 let sleep_ns = 1_000_000; let time1 = time_get(ClockId::Monotonic);
623 nanosleep(deadline_after(sleep_ns));
624 let time2 = time_get(ClockId::Monotonic);
625 assert!(time2 > time1 + sleep_ns);
626 }
627
628 #[test]
630 fn duplicate() {
631 let hello_length: usize = 5;
632
633 let vmo = Vmo::create(hello_length as u64, VmoOpts::Default).unwrap();
635 assert!(vmo.write(b"hello", 0).is_ok());
636
637 let readonly_vmo = vmo.duplicate(MX_RIGHT_READ).unwrap();
639 let mut read_vec = vec![0; hello_length];
641 assert_eq!(readonly_vmo.read(&mut read_vec, 0).unwrap(), hello_length);
642 assert_eq!(read_vec, b"hello");
643 assert_eq!(readonly_vmo.write(b"", 0), Err(Status::ErrAccessDenied));
644
645 assert!(vmo.write(b"bye", 0).is_ok());
647 assert_eq!(readonly_vmo.read(&mut read_vec, 0).unwrap(), hello_length);
648 assert_eq!(read_vec, b"byelo");
649 }
650
651 #[test]
653 fn replace() {
654 let hello_length: usize = 5;
655
656 let vmo = Vmo::create(hello_length as u64, VmoOpts::Default).unwrap();
658 assert!(vmo.write(b"hello", 0).is_ok());
659
660 let readonly_vmo = vmo.replace(MX_RIGHT_READ).unwrap();
662 let mut read_vec = vec![0; hello_length];
664 assert_eq!(readonly_vmo.read(&mut read_vec, 0).unwrap(), hello_length);
665 assert_eq!(read_vec, b"hello");
666 assert_eq!(readonly_vmo.write(b"", 0), Err(Status::ErrAccessDenied));
667 }
668
669 #[test]
670 fn wait_and_signal() {
671 let event = Event::create(EventOpts::Default).unwrap();
672 let ten_ms: Duration = 10_000_000;
673
674 assert_eq!(event.wait(MX_USER_SIGNAL_0, deadline_after(ten_ms)), Err(Status::ErrTimedOut));
676
677 assert!(event.signal(MX_SIGNAL_NONE, MX_USER_SIGNAL_0).is_ok());
679 assert_eq!(event.wait(MX_USER_SIGNAL_0, deadline_after(ten_ms)).unwrap(),
680 MX_USER_SIGNAL_0 | MX_SIGNAL_LAST_HANDLE);
681
682 assert_eq!(event.wait(MX_USER_SIGNAL_0, deadline_after(ten_ms)).unwrap(),
684 MX_USER_SIGNAL_0 | MX_SIGNAL_LAST_HANDLE);
685
686 assert!(event.signal(MX_USER_SIGNAL_0, MX_SIGNAL_NONE).is_ok());
688 assert_eq!(event.wait(MX_USER_SIGNAL_0, deadline_after(ten_ms)), Err(Status::ErrTimedOut));
689 }
690
691 #[test]
692 fn wait_many_and_signal() {
693 let ten_ms: Duration = 10_000_000;
694 let e1 = Event::create(EventOpts::Default).unwrap();
695 let e2 = Event::create(EventOpts::Default).unwrap();
696
697 let mut items = vec![
699 WaitItem { handle: e1.as_handle_ref(), waitfor: MX_USER_SIGNAL_0, pending: MX_SIGNAL_NONE },
700 WaitItem { handle: e2.as_handle_ref(), waitfor: MX_USER_SIGNAL_1, pending: MX_SIGNAL_NONE },
701 ];
702 assert_eq!(object_wait_many(&mut items, deadline_after(ten_ms)), Err(Status::ErrTimedOut));
703 assert_eq!(items[0].pending, MX_SIGNAL_LAST_HANDLE);
704 assert_eq!(items[1].pending, MX_SIGNAL_LAST_HANDLE);
705
706 assert!(e1.signal(MX_SIGNAL_NONE, MX_USER_SIGNAL_0).is_ok());
708 assert!(object_wait_many(&mut items, deadline_after(ten_ms)).is_ok());
709 assert_eq!(items[0].pending, MX_USER_SIGNAL_0 | MX_SIGNAL_LAST_HANDLE);
710 assert_eq!(items[1].pending, MX_SIGNAL_LAST_HANDLE);
711
712 assert!(e2.signal(MX_SIGNAL_NONE, MX_USER_SIGNAL_1).is_ok());
714 assert!(object_wait_many(&mut items, deadline_after(ten_ms)).is_ok());
715 assert_eq!(items[0].pending, MX_USER_SIGNAL_0 | MX_SIGNAL_LAST_HANDLE);
716 assert_eq!(items[1].pending, MX_USER_SIGNAL_1 | MX_SIGNAL_LAST_HANDLE);
717
718 assert!(e1.signal(MX_USER_SIGNAL_0, MX_SIGNAL_NONE).is_ok());
720 assert!(e2.signal(MX_USER_SIGNAL_1, MX_SIGNAL_NONE).is_ok());
721 assert_eq!(object_wait_many(&mut items, deadline_after(ten_ms)), Err(Status::ErrTimedOut));
722 assert_eq!(items[0].pending, MX_SIGNAL_LAST_HANDLE);
723 assert_eq!(items[1].pending, MX_SIGNAL_LAST_HANDLE);
724 }
725
726 #[test]
727 fn cookies() {
728 let event = Event::create(EventOpts::Default).unwrap();
729 let scope = Event::create(EventOpts::Default).unwrap();
730
731 assert_eq!(event.get_cookie(&scope.as_handle_ref()), Err(Status::ErrAccessDenied));
733
734 assert_eq!(event.set_cookie(&scope.as_handle_ref(), 42), Ok(()));
736
737 assert_eq!(event.get_cookie(&scope.as_handle_ref()), Ok(42));
739
740 assert_eq!(event.get_cookie(&event.as_handle_ref()), Err(Status::ErrAccessDenied));
742
743 assert_eq!(event.set_cookie(&scope.as_handle_ref(), 123), Ok(()));
745
746 assert_eq!(event.set_cookie(&event.as_handle_ref(), 123), Err(Status::ErrAccessDenied));
748 }
749
750 #[test]
751 fn cprng() {
752 let mut buffer = [0; 20];
753 assert_eq!(cprng_draw(&mut buffer), Ok(20));
754 assert_ne!(buffer[0], 0);
755 assert_ne!(buffer[19], 0);
756 }
757
758 #[test]
759 fn cprng_too_large() {
760 let mut buffer = [0; MX_CPRNG_DRAW_MAX_LEN + 1];
761 assert_eq!(cprng_draw(&mut buffer), Err(Status::ErrInvalidArgs));
762
763 for mut s in buffer.chunks_mut(MX_CPRNG_DRAW_MAX_LEN) {
764 assert_eq!(cprng_draw(&mut s), Ok(s.len()));
765 }
766 }
767
768 #[test]
769 fn cprng_add() {
770 let buffer = [0, 1, 2];
771 assert_eq!(cprng_add_entropy(&buffer), Ok(()));
772 }
773}
774
775pub fn usize_into_u32(n: usize) -> Result<u32, ()> {
776 if n > ::std::u32::MAX as usize || n < ::std::u32::MIN as usize {
777 return Err(())
778 }
779 Ok(n as u32)
780}
781
782pub fn size_to_u32_sat(n: usize) -> u32 {
783 if n > ::std::u32::MAX as usize {
784 return ::std::u32::MAX;
785 }
786 if n < ::std::u32::MIN as usize {
787 return ::std::u32::MIN;
788 }
789 n as u32
790}