OLD | NEW |
| (Empty) |
1 // Copyright 2016 The Chromium 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. | |
4 | |
5 use std::mem; | |
6 use std::slice; | |
7 use std::ptr; | |
8 | |
9 use system::ffi; | |
10 // This full import is intentional; nearly every type in mojo_types needs to be
used. | |
11 use system::mojo_types::*; | |
12 use system::handle; | |
13 use system::handle::{CastHandle, Handle}; | |
14 | |
15 #[repr(u32)] | |
16 /// Create flags for shared buffers | |
17 pub enum Create { | |
18 None = 0, | |
19 } | |
20 | |
21 #[repr(u32)] | |
22 /// Duplicate flags for shared buffers | |
23 pub enum Duplicate { | |
24 None = 0, | |
25 } | |
26 | |
27 #[repr(u32)] | |
28 /// Map flags for shared buffers | |
29 pub enum Map { | |
30 None = 0, | |
31 } | |
32 | |
33 #[repr(u32)] | |
34 /// Map flags for shared buffers | |
35 pub enum Info { | |
36 None = 0, | |
37 } | |
38 | |
39 /// A MappedBuffer represents the result of | |
40 /// calling map_buffer on a shared buffer handle. | |
41 /// | |
42 /// The C API allocates a buffer which can then be | |
43 /// read or written to through this data structure. | |
44 /// | |
45 /// The importance of this data structure is that | |
46 /// we bind the lifetime of the slice given to us | |
47 /// from the C API to this structure. Additionally, | |
48 /// reads and writes to this data structure are guaranteed | |
49 /// to be able to propagate through Mojo as they are | |
50 /// volatile. Language optimization backends are generally | |
51 /// unaware of other address spaces, and since this structure | |
52 /// represents some buffer from another address space, we | |
53 /// need to make sure loads and stores are volatile. | |
54 /// | |
55 /// Changes to this data structure are propagated through Mojo | |
56 /// on the next Mojo operation (that is, Mojo operations are | |
57 /// considered barriers). So, unmapping the buffer, sending a | |
58 /// message across a pipe, duplicating a shared buffer handle, | |
59 /// etc. are all valid ways of propagating changes. The read | |
60 /// and write methods do NOT guarantee changes to propagate. | |
61 /// | |
62 /// This structure also prevents resource leaks by | |
63 /// unmapping the buffer it contains on destruction. | |
64 pub struct MappedBuffer<'a> { | |
65 buffer: &'a mut [u8], | |
66 } | |
67 | |
68 impl<'a> MappedBuffer<'a> { | |
69 /// Returns the length of the wrapped buffer. | |
70 /// | |
71 /// Part of reimplementing the array interface to be | |
72 /// able to use the structure naturally. | |
73 pub fn len(&self) -> usize { | |
74 self.buffer.len() | |
75 } | |
76 | |
77 /// Read safely from the shared buffer. Makes sure a real load | |
78 /// is performed by marking the read as volatile. | |
79 pub fn read(&self, index: usize) -> u8 { | |
80 unsafe { ptr::read_volatile((&self.buffer[index]) as *const u8) } | |
81 } | |
82 | |
83 /// Write safely to the shared buffer. Makes sure a real store | |
84 /// is performed by marking the store as volatile. | |
85 pub fn write(&mut self, index: usize, value: u8) { | |
86 unsafe { | |
87 ptr::write_volatile((&mut self.buffer[index]) as *mut u8, value); | |
88 } | |
89 } | |
90 | |
91 /// Returns the slice this buffer wraps. | |
92 /// | |
93 /// The reason this method is unsafe is because the way Rust maps | |
94 /// reads and writes down to loads and stores may not be to real | |
95 /// loads and stores which are required to allow changes to propagate | |
96 /// through Mojo. If you are not careful, some writes and reads may be | |
97 /// to incorrect data! Use at your own risk. | |
98 pub unsafe fn as_slice(&'a mut self) -> &'a mut [u8] { | |
99 self.buffer | |
100 } | |
101 } | |
102 | |
103 impl<'a> Drop for MappedBuffer<'a> { | |
104 /// The destructor for MappedBuffer. Unmaps the buffer it | |
105 /// encloses by using the original, raw pointer to the mapped | |
106 /// memory region. | |
107 fn drop(&mut self) { | |
108 let r = MojoResult::from_code(unsafe { | |
109 ffi::MojoUnmapBuffer(self.buffer.as_ptr() as *const ffi::c_void) | |
110 }); | |
111 if r != MojoResult::Okay { | |
112 panic!("Failed to unmap buffer. Mojo Error: {}", r); | |
113 } | |
114 } | |
115 } | |
116 | |
117 /// Creates a shared buffer in Mojo and returns a SharedBuffer | |
118 /// structure which represents a handle to the shared buffer. | |
119 pub fn create(flags: CreateFlags, num_bytes: u64) -> Result<SharedBuffer, MojoRe
sult> { | |
120 let opts = ffi::MojoCreateSharedBufferOptions { | |
121 struct_size: mem::size_of::<ffi::MojoCreateSharedBufferOptions>() as u32
, | |
122 flags: flags, | |
123 _align: [], | |
124 }; | |
125 let raw_opts = &opts as *const ffi::MojoCreateSharedBufferOptions; | |
126 let mut h: MojoHandle = 0; | |
127 let r = MojoResult::from_code(unsafe { | |
128 ffi::MojoCreateSharedBuffer(raw_opts, num_bytes, &mut h as *mut MojoHand
le) | |
129 }); | |
130 if r != MojoResult::Okay { | |
131 Err(r) | |
132 } else { | |
133 Ok(SharedBuffer { handle: unsafe { handle::acquire(h) } }) | |
134 } | |
135 } | |
136 | |
137 /// Represents a handle to a shared buffer in Mojo. | |
138 /// This data structure wraps a handle and acts | |
139 /// effectively as a typed handle. | |
140 pub struct SharedBuffer { | |
141 handle: handle::UntypedHandle, | |
142 } | |
143 | |
144 impl SharedBuffer { | |
145 /// Duplicates the shared buffer handle. This is NOT the same | |
146 /// as cloning the structure which is illegal since cloning could | |
147 /// lead to resource leaks. Instead this uses Mojo to duplicate the | |
148 /// buffer handle (though the handle itself may not be represented by | |
149 /// the same number) that maps to the same shared buffer as the original. | |
150 pub fn duplicate(&self, flags: DuplicateFlags) -> Result<SharedBuffer, MojoR
esult> { | |
151 let opts = ffi::MojoDuplicateBufferHandleOptions { | |
152 struct_size: mem::size_of::<ffi::MojoDuplicateBufferHandleOptions>()
as u32, | |
153 flags: flags, | |
154 _align: [], | |
155 }; | |
156 let raw_opts = &opts as *const ffi::MojoDuplicateBufferHandleOptions; | |
157 let mut dup_h: MojoHandle = 0; | |
158 let r = MojoResult::from_code(unsafe { | |
159 ffi::MojoDuplicateBufferHandle(self.handle.get_native_handle(), | |
160 raw_opts, | |
161 &mut dup_h as *mut MojoHandle) | |
162 }); | |
163 if r != MojoResult::Okay { | |
164 Err(r) | |
165 } else { | |
166 Ok(SharedBuffer { handle: unsafe { handle::acquire(dup_h) } }) | |
167 } | |
168 } | |
169 | |
170 /// Map the shared buffer into local memory. Generates a MappedBuffer | |
171 /// structure. See MappedBuffer for more information on how to use it. | |
172 pub fn map<'a>(&self, | |
173 offset: u64, | |
174 num_bytes: u64, | |
175 flags: MapFlags) | |
176 -> Result<MappedBuffer<'a>, MojoResult> { | |
177 unsafe { | |
178 let mut ptr: *mut ffi::c_void = mem::uninitialized(); | |
179 let r = MojoResult::from_code(ffi::MojoMapBuffer(self.handle.get_nat
ive_handle(), | |
180 offset, | |
181 num_bytes, | |
182 &mut ptr, | |
183 flags)); | |
184 if r != MojoResult::Okay { | |
185 Err(r) | |
186 } else { | |
187 let mut buf = slice::from_raw_parts_mut(ptr as *mut u8, num_byte
s as usize); | |
188 Ok(MappedBuffer { buffer: buf }) | |
189 } | |
190 } | |
191 } | |
192 | |
193 /// Retrieves information about a shared buffer the this handle. The return | |
194 /// value is a set of flags (a bit vector in a u32) representing different | |
195 /// aspects of the shared buffer and the size of the shared buffer. | |
196 pub fn get_info(&self) -> Result<(InfoFlags, u64), MojoResult> { | |
197 let info_size = mem::size_of::<ffi::MojoBufferInformation>() as u32; | |
198 let mut info = ffi::MojoBufferInformation { | |
199 struct_size: info_size, | |
200 flags: 0, | |
201 num_bytes: 0, | |
202 _align: [], | |
203 }; | |
204 let r = MojoResult::from_code(unsafe { | |
205 ffi::MojoGetBufferInformation(self.handle.get_native_handle(), | |
206 &mut info as *mut ffi::MojoBufferInfor
mation, | |
207 info_size) | |
208 }); | |
209 if r != MojoResult::Okay { | |
210 Err(r) | |
211 } else { | |
212 Ok((info.flags, info.num_bytes)) | |
213 } | |
214 } | |
215 } | |
216 | |
217 impl CastHandle for SharedBuffer { | |
218 /// Generates a SharedBuffer from an untyped handle wrapper | |
219 /// See mojo::system::handle for information on untyped vs. typed | |
220 unsafe fn from_untyped(handle: handle::UntypedHandle) -> Self { | |
221 SharedBuffer { handle: handle } | |
222 } | |
223 | |
224 /// Consumes this object and produces a plain handle wrapper | |
225 /// See mojo::system::handle for information on untyped vs. typed | |
226 fn as_untyped(self) -> handle::UntypedHandle { | |
227 self.handle | |
228 } | |
229 } | |
230 | |
231 impl Handle for SharedBuffer { | |
232 /// Returns the native handle wrapped by this structure. | |
233 /// | |
234 /// See mojo::system::handle for information on handle wrappers | |
235 fn get_native_handle(&self) -> MojoHandle { | |
236 self.handle.get_native_handle() | |
237 } | |
238 } | |
OLD | NEW |