• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Chromium OS 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 use std::convert::TryFrom;
5 use std::io;
6 use std::mem;
7 use std::os::unix::io::{AsRawFd, RawFd};
8 use std::ptr;
9 use std::ptr::NonNull;
10 use std::slice;
11 use std::sync::atomic::{self, Ordering};
12 use std::thread;
13 
14 use cras_sys::gen::{
15     audio_dev_debug_info, audio_stream_debug_info, cras_audio_shm_header, cras_iodev_info,
16     cras_ionode_info, cras_server_state, CRAS_MAX_IODEVS, CRAS_MAX_IONODES, CRAS_NUM_SHM_BUFFERS,
17     CRAS_SERVER_STATE_VERSION, CRAS_SHM_BUFFERS_MASK, MAX_DEBUG_DEVS, MAX_DEBUG_STREAMS,
18 };
19 use cras_sys::{
20     AudioDebugInfo, AudioDevDebugInfo, AudioStreamDebugInfo, CrasIodevInfo, CrasIonodeInfo,
21 };
22 use data_model::{VolatileRef, VolatileSlice};
23 use sys_util::warn;
24 
25 /// A structure wrapping a fd which contains a shared `cras_audio_shm_header`.
26 /// * `shm_fd` - A shared memory fd contains a `cras_audio_shm_header`
27 pub struct CrasAudioShmHeaderFd {
28     fd: CrasShmFd,
29 }
30 
31 impl CrasAudioShmHeaderFd {
32     /// Creates a `CrasAudioShmHeaderFd` by shared memory fd
33     /// # Arguments
34     /// * `fd` - A shared memory file descriptor, which will be owned by the resulting structure and
35     /// the fd will be closed on drop.
36     ///
37     /// # Returns
38     /// A structure wrapping a `CrasShmFd` with the input fd and `size` which equals to
39     /// the size of `cras_audio_shm_header`.
40     ///
41     /// To use this function safely, we need to make sure
42     /// - The input fd is a valid shared memory fd.
43     /// - The input shared memory fd won't be used by others.
44     /// - The shared memory area in the input fd contains a `cras_audio_shm_header`.
new(fd: libc::c_int) -> Self45     pub unsafe fn new(fd: libc::c_int) -> Self {
46         Self {
47             fd: CrasShmFd::new(fd, mem::size_of::<cras_audio_shm_header>()),
48         }
49     }
50 }
51 
52 /// A wrapper for the raw structure `cras_audio_shm_header` with
53 /// size information for the separate audio samples shm area and several
54 /// `VolatileRef` to sub fields for safe access to the header.
55 pub struct CrasAudioHeader<'a> {
56     addr: *mut libc::c_void,
57     /// Size of the buffer for samples in CrasAudioBuffer
58     samples_len: usize,
59     used_size: VolatileRef<'a, u32>,
60     frame_size: VolatileRef<'a, u32>,
61     read_buf_idx: VolatileRef<'a, u32>,
62     write_buf_idx: VolatileRef<'a, u32>,
63     read_offset: [VolatileRef<'a, u32>; CRAS_NUM_SHM_BUFFERS as usize],
64     write_offset: [VolatileRef<'a, u32>; CRAS_NUM_SHM_BUFFERS as usize],
65     buffer_offset: [VolatileRef<'a, u64>; CRAS_NUM_SHM_BUFFERS as usize],
66 }
67 
68 // It is safe to send audio buffers between threads as this struct has exclusive ownership of the
69 // pointers contained in it.
70 unsafe impl<'a> Send for CrasAudioHeader<'a> {}
71 
72 /// An unsafe macro for getting `VolatileRef` for a field from a given NonNull pointer.
73 /// It Supports
74 /// - Nested sub-field
75 /// - Element of an array field
76 ///
77 /// To use this macro safely, we need to
78 /// - Make sure the pointer address is readable and writable for its structure.
79 /// - Make sure all `VolatileRef`s generated from this macro have exclusive ownership for the same
80 /// pointer.
81 #[macro_export]
82 macro_rules! vref_from_addr {
83     ($addr:ident, $($field:ident).*) => {
84         VolatileRef::new(&mut $addr.as_mut().$($field).* as *mut _)
85     };
86 
87     ($addr:ident, $field:ident[$idx:tt]) => {
88         VolatileRef::new(&mut $addr.as_mut().$field[$idx] as *mut _)
89     };
90 }
91 
92 // Generates error when an index is out of range.
index_out_of_range() -> io::Error93 fn index_out_of_range() -> io::Error {
94     io::Error::new(io::ErrorKind::InvalidInput, "Index out of range.")
95 }
96 
97 impl<'a> CrasAudioHeader<'a> {
98     // Creates a `CrasAudioHeader` with given `CrasAudioShmHeaderFd` and `samples_len`
new(header_fd: CrasAudioShmHeaderFd, samples_len: usize) -> io::Result<Self>99     fn new(header_fd: CrasAudioShmHeaderFd, samples_len: usize) -> io::Result<Self> {
100         // Safe because the creator of CrasAudioShmHeaderFd already
101         // ensured that header_fd contains a cras_audio_shm_header.
102         let mmap_addr = unsafe {
103             cras_mmap(
104                 header_fd.fd.size,
105                 libc::PROT_READ | libc::PROT_WRITE,
106                 header_fd.fd.as_raw_fd(),
107             )?
108         };
109 
110         let mut addr = NonNull::new(mmap_addr as *mut cras_audio_shm_header)
111             .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Failed to create header."))?;
112 
113         // Safe because we know that mmap_addr (contained in addr) contains a
114         // cras_audio_shm_header, and the mapped area will be exclusively
115         // owned by this struct.
116         unsafe {
117             Ok(CrasAudioHeader {
118                 addr: addr.as_ptr() as *mut libc::c_void,
119                 samples_len,
120                 used_size: vref_from_addr!(addr, config.used_size),
121                 frame_size: vref_from_addr!(addr, config.frame_bytes),
122                 read_buf_idx: vref_from_addr!(addr, read_buf_idx),
123                 write_buf_idx: vref_from_addr!(addr, write_buf_idx),
124                 read_offset: [
125                     vref_from_addr!(addr, read_offset[0]),
126                     vref_from_addr!(addr, read_offset[1]),
127                 ],
128                 write_offset: [
129                     vref_from_addr!(addr, write_offset[0]),
130                     vref_from_addr!(addr, write_offset[1]),
131                 ],
132                 buffer_offset: [
133                     vref_from_addr!(addr, buffer_offset[0]),
134                     vref_from_addr!(addr, buffer_offset[1]),
135                 ],
136             })
137         }
138     }
139 
140     /// Calculates the length of a buffer with the given offset. This length will
141     /// be `used_size`, unless the offset is closer than `used_size` to the end
142     /// of samples, in which case the length will be as long as possible.
143     ///
144     /// If that buffer length is invalid (too small to hold a frame of audio data),
145     /// then returns an error.
146     /// The returned buffer length will be rounded down to a multiple of `frame_size`.
buffer_len_from_offset(&self, offset: usize) -> io::Result<usize>147     fn buffer_len_from_offset(&self, offset: usize) -> io::Result<usize> {
148         if offset > self.samples_len {
149             return Err(io::Error::new(
150                 io::ErrorKind::InvalidInput,
151                 format!(
152                     "Buffer offset {} exceeds the length of samples area ({}).",
153                     offset, self.samples_len
154                 ),
155             ));
156         }
157 
158         let used_size = self.get_used_size();
159         let frame_size = self.get_frame_size();
160 
161         // We explicitly allow a buffer shorter than used_size, but only
162         // at the end of the samples area.
163         // This is useful if we're playing a file where the number of samples is
164         // not a multiple of used_size (meaning the length of the samples area
165         // won't be either). Then, the last buffer played will be smaller than
166         // used_size.
167         let mut buffer_length = used_size.min(self.samples_len - offset);
168         if buffer_length < frame_size {
169             return Err(io::Error::new(
170                 io::ErrorKind::InvalidInput,
171                 format!(
172                     "Buffer offset {} gives buffer length {} smaller than frame size {}.",
173                     offset, buffer_length, frame_size
174                 ),
175             ));
176         }
177 
178         // Round buffer_length down to a multiple of frame size
179         buffer_length = buffer_length / frame_size * frame_size;
180         Ok(buffer_length)
181     }
182 
183     /// Gets the base of the write buffer and the writable length (rounded to `frame_size`).
184     /// Does not take into account the write offset.
185     ///
186     /// # Returns
187     ///
188     ///  * (`usize`, `usize`) - write buffer base as an offset from the start of
189     ///                         the samples area and buffer length in bytes.
get_write_offset_and_len(&self) -> io::Result<(usize, usize)>190     pub fn get_write_offset_and_len(&self) -> io::Result<(usize, usize)> {
191         let idx = self.get_write_buf_idx() as usize;
192         let offset = self.get_buffer_offset(idx)?;
193         let len = self.buffer_len_from_offset(offset)?;
194 
195         Ok((offset, len))
196     }
197 
198     /// Gets the buffer offset of the read buffer.
199     ///
200     ///  # Returns
201     ///
202     ///  * `usize` - read offset in bytes
get_read_buffer_offset(&self) -> io::Result<usize>203     pub fn get_read_buffer_offset(&self) -> io::Result<usize> {
204         let idx = self.get_read_buf_idx() as usize;
205         self.get_buffer_offset(idx)
206     }
207 
208     /// Gets the offset of a buffer from the start of samples.
209     ///
210     /// # Arguments
211     /// `index` - 0 <= `index` < `CRAS_NUM_SHM_BUFFERS`. The index of the buffer
212     /// for which we want the `buffer_offset`.
213     ///
214     /// # Returns
215     /// * `usize` - buffer offset in bytes
get_buffer_offset(&self, idx: usize) -> io::Result<usize>216     fn get_buffer_offset(&self, idx: usize) -> io::Result<usize> {
217         let buffer_offset = self
218             .buffer_offset
219             .get(idx)
220             .ok_or_else(index_out_of_range)?
221             .load() as usize;
222         self.check_buffer_offset(idx, buffer_offset)?;
223         Ok(buffer_offset)
224     }
225 
226     /// Gets the number of bytes per frame from the shared memory structure.
227     ///
228     /// # Returns
229     ///
230     /// * `usize` - Number of bytes per frame
get_frame_size(&self) -> usize231     pub fn get_frame_size(&self) -> usize {
232         self.frame_size.load() as usize
233     }
234 
235     /// Gets the max size in bytes of each shared memory buffer within
236     /// the samples area.
237     ///
238     /// # Returns
239     ///
240     /// * `usize` - Value of `used_size` fetched from the shared memory header.
get_used_size(&self) -> usize241     pub fn get_used_size(&self) -> usize {
242         self.used_size.load() as usize
243     }
244 
245     /// Gets the index of the current written buffer.
246     ///
247     /// # Returns
248     /// `u32` - the returned index is less than `CRAS_NUM_SHM_BUFFERS`.
get_write_buf_idx(&self) -> u32249     fn get_write_buf_idx(&self) -> u32 {
250         self.write_buf_idx.load() & CRAS_SHM_BUFFERS_MASK
251     }
252 
get_read_buf_idx(&self) -> u32253     fn get_read_buf_idx(&self) -> u32 {
254         self.read_buf_idx.load() & CRAS_SHM_BUFFERS_MASK
255     }
256 
257     /// Switches the written buffer.
switch_write_buf_idx(&mut self)258     fn switch_write_buf_idx(&mut self) {
259         self.write_buf_idx
260             .store(self.get_write_buf_idx() as u32 ^ 1u32)
261     }
262 
263     /// Switches the buffer to read.
switch_read_buf_idx(&mut self)264     fn switch_read_buf_idx(&mut self) {
265         self.read_buf_idx
266             .store(self.get_read_buf_idx() as u32 ^ 1u32)
267     }
268 
269     /// Checks if the offset value for setting write_offset or read_offset is
270     /// out of range or not.
271     ///
272     /// # Arguments
273     /// `idx` - The index of the buffer for which we're checking the offset.
274     /// `offset` - 0 <= `offset` <= `used_size` && `buffer_offset[idx]` + `offset` <=
275     /// `samples_len`. Writable or readable size equals to 0 when offset equals
276     /// to `used_size`.
277     ///
278     /// # Errors
279     /// Returns an error if `offset` is out of range or if idx is not a valid
280     /// buffer idx.
check_rw_offset(&self, idx: usize, offset: u32) -> io::Result<()>281     fn check_rw_offset(&self, idx: usize, offset: u32) -> io::Result<()> {
282         let buffer_len = self.buffer_len_from_offset(self.get_buffer_offset(idx)?)?;
283         if offset as usize > buffer_len {
284             return Err(io::Error::new(
285                 io::ErrorKind::InvalidInput,
286                 format!(
287                     "Offset {} is larger than buffer size {}.",
288                     offset, buffer_len
289                 ),
290             ));
291         }
292 
293         Ok(())
294     }
295 
296     /// Sets `write_offset[idx]` to the count of written bytes.
297     ///
298     /// # Arguments
299     /// `idx` - 0 <= `idx` < `CRAS_NUM_SHM_BUFFERS`
300     /// `offset` - 0 <= `offset` <= `used_size` && `offset` + `used_size` <=
301     /// `samples_len`. Writable size equals to 0 when offset equals to
302     /// `used_size`.
303     ///
304     /// # Errors
305     /// Returns an error if `offset` is out of range.
set_write_offset(&mut self, idx: usize, offset: u32) -> io::Result<()>306     fn set_write_offset(&mut self, idx: usize, offset: u32) -> io::Result<()> {
307         self.check_rw_offset(idx, offset)?;
308         let write_offset = self.write_offset.get(idx).ok_or_else(index_out_of_range)?;
309         write_offset.store(offset);
310         Ok(())
311     }
312 
313     /// Sets `read_offset[idx]` to count of written bytes.
314     ///
315     /// # Arguments
316     /// `idx` - 0 <= `idx` < `CRAS_NUM_SHM_BUFFERS`
317     /// `offset` - 0 <= `offset` <= `used_size` && `offset` + `used_size` <=
318     /// `samples_len`. Readable size equals to 0 when offset equals to
319     /// `used_size`.
320     ///
321     /// # Errors
322     /// Returns error if index out of range.
set_read_offset(&mut self, idx: usize, offset: u32) -> io::Result<()>323     fn set_read_offset(&mut self, idx: usize, offset: u32) -> io::Result<()> {
324         self.check_rw_offset(idx, offset)?;
325         let read_offset = self.read_offset.get(idx).ok_or_else(index_out_of_range)?;
326         read_offset.store(offset);
327         Ok(())
328     }
329 
330     /// Check that `offset` is a valid buffer offset for the buffer at `idx`
331     /// An offset is not valid if it is
332     ///  * outside of the samples area
333     ///  * overlaps some other buffer `[other_offset, other_offset + used_size)`
334     ///  * is close enough to the end of the samples area that the buffer would
335     ///    be shorter than `frame_size`.
check_buffer_offset(&self, idx: usize, offset: usize) -> io::Result<()>336     fn check_buffer_offset(&self, idx: usize, offset: usize) -> io::Result<()> {
337         let start = offset;
338         let end = start + self.buffer_len_from_offset(start)?;
339 
340         let other_idx = (idx ^ 1) as usize;
341         let other_start = self
342             .buffer_offset
343             .get(other_idx)
344             .ok_or_else(index_out_of_range)?
345             .load() as usize;
346         let other_end = other_start + self.buffer_len_from_offset(other_start)?;
347         if start < other_end && other_start < end {
348             // Special case: occasionally we get the same buffer offset twice
349             // from the intel8x0 kernel driver in crosvm's AC97 device, and we
350             // don't want to crash in that case.
351             if start == other_start && end == other_end {
352                 warn!(
353                     "Setting buffer {} to same index/offset as buffer {}, [{}, {})",
354                     idx, other_idx, other_start, other_end
355                 );
356             } else {
357                 return Err(io::Error::new(
358                     io::ErrorKind::InvalidInput,
359                     format!(
360                         "Setting buffer {} to [{}, {}) overlaps buffer {} at [{}, {})",
361                         idx, start, end, other_idx, other_start, other_end,
362                     ),
363                 ));
364             }
365         }
366         Ok(())
367     }
368 
369     /// Sets the location of the audio buffer `idx` within the samples area to
370     /// `offset`, so that CRAS will read/write samples for that buffer from that
371     /// offset.
372     ///
373     /// # Arguments
374     /// `idx` - 0 <= `idx` < `CRAS_NUM_SHM_BUFFERS`
375     /// `offset` - 0 <= `offset` && `offset` + `frame_size` <= `samples_len`
376     ///
377     /// # Errors
378     /// If `idx` is out of range
379     /// If the offset is invalid, which can happen if `offset` is
380     ///  * outside of the samples area
381     ///  * overlaps some other buffer `[other_offset, other_offset + used_size)`
382     ///  * is close enough to the end of the samples area that the buffer would
383     ///    be shorter than `frame_size`.
set_buffer_offset(&mut self, idx: usize, offset: usize) -> io::Result<()>384     pub fn set_buffer_offset(&mut self, idx: usize, offset: usize) -> io::Result<()> {
385         self.check_buffer_offset(idx, offset)?;
386 
387         let buffer_offset = self.buffer_offset.get(idx).ok_or_else(index_out_of_range)?;
388         buffer_offset.store(offset as u64);
389         Ok(())
390     }
391 
392     /// Commits written frames by switching the current buffer to the other one
393     /// after samples are ready and indexes of current buffer are all set.
394     /// - Sets `write_offset` of current buffer to `frame_count * frame_size`
395     /// - Sets `read_offset` of current buffer to `0`.
396     ///
397     /// # Arguments
398     ///
399     /// * `frame_count` - Number of frames written to the current buffer
400     ///
401     /// # Errors
402     ///
403     /// * Returns error if `frame_count` is larger than buffer size
404     ///
405     /// This function is safe because we switch `write_buf_idx` after letting
406     /// `write_offset` and `read_offset` ready and we read / write shared memory
407     /// variables with volatile operations.
commit_written_frames(&mut self, frame_count: u32) -> io::Result<()>408     pub fn commit_written_frames(&mut self, frame_count: u32) -> io::Result<()> {
409         // Uses `u64` to prevent possible overflow
410         let byte_count = frame_count as u64 * self.get_frame_size() as u64;
411         if byte_count > self.get_used_size() as u64 {
412             Err(io::Error::new(
413                 io::ErrorKind::InvalidInput,
414                 "frame_count * frame_size is larger than used_size",
415             ))
416         } else {
417             let idx = self.get_write_buf_idx() as usize;
418             // Sets `write_offset` of current buffer to frame_count * frame_size
419             self.set_write_offset(idx, byte_count as u32)?;
420             // Sets `read_offset` of current buffer to `0`.
421             self.set_read_offset(idx, 0)?;
422             // Switch to the other buffer
423             self.switch_write_buf_idx();
424             Ok(())
425         }
426     }
427 
428     /// Get readable frames in current buffer.
429     ///
430     /// # Returns
431     ///
432     /// * `usize` - number of readable frames.
433     ///
434     /// # Errors
435     ///
436     /// Returns error if index out of range.
get_readable_frames(&self) -> io::Result<usize>437     pub fn get_readable_frames(&self) -> io::Result<usize> {
438         let idx = self.get_read_buf_idx() as usize;
439         let read_offset = self.read_offset.get(idx).ok_or_else(index_out_of_range)?;
440         let write_offset = self.write_offset.get(idx).ok_or_else(index_out_of_range)?;
441         let nframes =
442             (write_offset.load() as i32 - read_offset.load() as i32) / self.get_frame_size() as i32;
443         if nframes < 0 {
444             Ok(0)
445         } else {
446             Ok(nframes as usize)
447         }
448     }
449 
450     /// Commit read frames from reader, .
451     /// - Sets `read_offset` of current buffer to `read_offset + frame_count * frame_size`.
452     /// If `read_offset` is larger than or equal to `write_offset`, then
453     /// - Sets `read_offset` and `write_offset` to `0` and switch `read_buf_idx`.
454     ///
455     /// # Arguments
456     ///
457     /// * `frame_count` - Read frames in current read buffer.
458     ///
459     /// # Errors
460     ///
461     /// Returns error if index out of range.
commit_read_frames(&mut self, frame_count: u32) -> io::Result<()>462     pub fn commit_read_frames(&mut self, frame_count: u32) -> io::Result<()> {
463         let idx = self.get_read_buf_idx() as usize;
464         let read_offset = self.read_offset.get(idx).ok_or_else(index_out_of_range)?;
465         let write_offset = self.write_offset.get(idx).ok_or_else(index_out_of_range)?;
466         read_offset.store(read_offset.load() + frame_count * self.get_frame_size() as u32);
467         if read_offset.load() >= write_offset.load() {
468             read_offset.store(0);
469             write_offset.store(0);
470             self.switch_read_buf_idx();
471         }
472         Ok(())
473     }
474 }
475 
476 impl<'a> Drop for CrasAudioHeader<'a> {
drop(&mut self)477     fn drop(&mut self) {
478         // Safe because all references must be gone by the time drop is called.
479         unsafe {
480             libc::munmap(self.addr as *mut _, mem::size_of::<cras_audio_shm_header>());
481         }
482     }
483 }
484 
485 // To use this safely, we need to make sure
486 // - The given fd contains valid space which is larger than `len` + `offset`
cras_mmap_offset( len: usize, prot: libc::c_int, fd: libc::c_int, offset: usize, ) -> io::Result<*mut libc::c_void>487 unsafe fn cras_mmap_offset(
488     len: usize,
489     prot: libc::c_int,
490     fd: libc::c_int,
491     offset: usize,
492 ) -> io::Result<*mut libc::c_void> {
493     if offset > libc::off_t::max_value() as usize {
494         return Err(io::Error::new(
495             io::ErrorKind::InvalidInput,
496             "Requested offset is out of range of `libc::off_t`.",
497         ));
498     }
499     // It's safe because we handle its returned results.
500     match libc::mmap(
501         ptr::null_mut(),
502         len,
503         prot,
504         libc::MAP_SHARED,
505         fd,
506         offset as libc::off_t,
507     ) {
508         libc::MAP_FAILED => Err(io::Error::last_os_error()),
509         shm_ptr => Ok(shm_ptr),
510     }
511 }
512 
513 // To use this safely, we need to make sure
514 // - The given fd contains valid space which is larger than `len`
cras_mmap( len: usize, prot: libc::c_int, fd: libc::c_int, ) -> io::Result<*mut libc::c_void>515 unsafe fn cras_mmap(
516     len: usize,
517     prot: libc::c_int,
518     fd: libc::c_int,
519 ) -> io::Result<*mut libc::c_void> {
520     cras_mmap_offset(len, prot, fd, 0)
521 }
522 
523 /// An unsafe macro for getting a `VolatileSlice` representing an entire array
524 /// field from a given NonNull pointer.
525 ///
526 /// To use this macro safely, we need to
527 /// - Make sure the pointer address is readable and writeable for its struct.
528 /// - Make sure all `VolatileSlice`s generated from this macro have exclusive ownership for the same
529 /// pointer.
530 /// - Make sure the length of the array field is non-zero.
531 #[macro_export]
532 macro_rules! vslice_from_addr {
533     ($addr:ident, $($field:ident).*) => {{
534         let ptr = &mut $addr.as_mut().$($field).* as *mut _ as *mut u8;
535         let size = std::mem::size_of_val(&$addr.as_mut().$($field).*);
536         VolatileSlice::from_raw_parts(ptr, size)
537     }};
538 }
539 
540 /// A structure that points to RO shared memory area - `cras_server_state`
541 /// The structure is created from a shared memory fd which contains the structure.
542 #[derive(Debug)]
543 pub struct CrasServerState<'a> {
544     addr: *mut libc::c_void,
545     volume: VolatileRef<'a, u32>,
546     mute: VolatileRef<'a, i32>,
547     num_output_devs: VolatileRef<'a, u32>,
548     output_devs: VolatileSlice<'a>,
549     num_input_devs: VolatileRef<'a, u32>,
550     input_devs: VolatileSlice<'a>,
551     num_output_nodes: VolatileRef<'a, u32>,
552     num_input_nodes: VolatileRef<'a, u32>,
553     output_nodes: VolatileSlice<'a>,
554     input_nodes: VolatileSlice<'a>,
555     update_count: VolatileRef<'a, u32>,
556     debug_info_num_devs: VolatileRef<'a, u32>,
557     debug_info_devs: VolatileSlice<'a>,
558     debug_info_num_streams: VolatileRef<'a, u32>,
559     debug_info_streams: VolatileSlice<'a>,
560 }
561 
562 // It is safe to send server_state between threads as this struct has exclusive
563 // ownership of the shared memory area contained in it.
564 unsafe impl<'a> Send for CrasServerState<'a> {}
565 
566 impl<'a> CrasServerState<'a> {
567     /// Create a CrasServerState
try_new(state_fd: CrasServerStateShmFd) -> io::Result<Self>568     pub fn try_new(state_fd: CrasServerStateShmFd) -> io::Result<Self> {
569         // Safe because the creator of CrasServerStateShmFd already
570         // ensured that state_fd contains a cras_server_state.
571         let mmap_addr =
572             unsafe { cras_mmap(state_fd.fd.size, libc::PROT_READ, state_fd.fd.as_raw_fd())? };
573 
574         let mut addr = NonNull::new(mmap_addr as *mut cras_server_state).ok_or_else(|| {
575             io::Error::new(io::ErrorKind::Other, "Failed to create CrasServerState.")
576         })?;
577 
578         // Safe because we know that addr is a non-null pointer to cras_server_state.
579         let state_version = unsafe { vref_from_addr!(addr, state_version) };
580         if state_version.load() != CRAS_SERVER_STATE_VERSION {
581             return Err(io::Error::new(
582                 io::ErrorKind::Other,
583                 format!(
584                     "CrasServerState version {} does not match expected version {}",
585                     state_version.load(),
586                     CRAS_SERVER_STATE_VERSION
587                 ),
588             ));
589         }
590 
591         // Safe because we know that mmap_addr (contained in addr) contains a
592         // cras_server_state, and the mapped area will be exclusively
593         // owned by this struct.
594         unsafe {
595             Ok(CrasServerState {
596                 addr: addr.as_ptr() as *mut libc::c_void,
597                 volume: vref_from_addr!(addr, volume),
598                 mute: vref_from_addr!(addr, mute),
599                 num_output_devs: vref_from_addr!(addr, num_output_devs),
600                 num_input_devs: vref_from_addr!(addr, num_input_devs),
601                 output_devs: vslice_from_addr!(addr, output_devs),
602                 input_devs: vslice_from_addr!(addr, input_devs),
603                 num_output_nodes: vref_from_addr!(addr, num_output_nodes),
604                 num_input_nodes: vref_from_addr!(addr, num_input_nodes),
605                 output_nodes: vslice_from_addr!(addr, output_nodes),
606                 input_nodes: vslice_from_addr!(addr, input_nodes),
607                 update_count: vref_from_addr!(addr, update_count),
608                 debug_info_num_devs: vref_from_addr!(addr, audio_debug_info.num_devs),
609                 debug_info_devs: vslice_from_addr!(addr, audio_debug_info.devs),
610                 debug_info_num_streams: vref_from_addr!(addr, audio_debug_info.num_streams),
611                 debug_info_streams: vslice_from_addr!(addr, audio_debug_info.streams),
612             })
613         }
614     }
615 
616     /// Gets the system volume.
617     ///
618     /// Read the current value for system volume from shared memory.
get_system_volume(&self) -> u32619     pub fn get_system_volume(&self) -> u32 {
620         self.volume.load()
621     }
622 
623     /// Gets the system mute.
624     ///
625     /// Read the current value for system mute from shared memory.
get_system_mute(&self) -> bool626     pub fn get_system_mute(&self) -> bool {
627         self.mute.load() != 0
628     }
629 
630     /// Runs a closure safely such that it can be sure that the server state
631     /// was not updated during the read.
632     /// This can be used for an "atomic" read of non-atomic data from the
633     /// state shared memory.
synchronized_state_read<F, T>(&self, mut func: F) -> T where F: FnMut() -> T,634     fn synchronized_state_read<F, T>(&self, mut func: F) -> T
635     where
636         F: FnMut() -> T,
637     {
638         // Waits until the server has completed a state update before returning
639         // the current update count.
640         let begin_server_state_read = || -> u32 {
641             loop {
642                 let update_count = self.update_count.load();
643                 if update_count % 2 == 0 {
644                     atomic::fence(Ordering::Acquire);
645                     return update_count;
646                 } else {
647                     thread::yield_now();
648                 }
649             }
650         };
651 
652         // Checks that the update count has not changed since the start
653         // of the server state read.
654         let end_server_state_read = |count: u32| -> bool {
655             let result = count == self.update_count.load();
656             atomic::fence(Ordering::Release);
657             result
658         };
659 
660         // Get the state's update count and run the provided closure.
661         // If the update count has not changed once the closure is finished,
662         // return the result, otherwise repeat the process.
663         loop {
664             let update_count = begin_server_state_read();
665             let result = func();
666             if end_server_state_read(update_count) {
667                 return result;
668             }
669         }
670     }
671 
672     /// Gets a list of output devices
673     ///
674     /// Read a list of the currently attached output devices from shared memory.
output_devices(&self) -> impl Iterator<Item = CrasIodevInfo>675     pub fn output_devices(&self) -> impl Iterator<Item = CrasIodevInfo> {
676         let mut devs: Vec<cras_iodev_info> = vec![Default::default(); CRAS_MAX_IODEVS as usize];
677         let num_devs = self.synchronized_state_read(|| {
678             self.output_devs.copy_to(&mut devs);
679             self.num_output_devs.load()
680         });
681         devs.into_iter()
682             .take(num_devs as usize)
683             .map(CrasIodevInfo::from)
684     }
685 
686     /// Gets a list of input devices
687     ///
688     /// Read a list of the currently attached input devices from shared memory.
input_devices(&self) -> impl Iterator<Item = CrasIodevInfo>689     pub fn input_devices(&self) -> impl Iterator<Item = CrasIodevInfo> {
690         let mut devs: Vec<cras_iodev_info> = vec![Default::default(); CRAS_MAX_IODEVS as usize];
691         let num_devs = self.synchronized_state_read(|| {
692             self.input_devs.copy_to(&mut devs);
693             self.num_input_devs.load()
694         });
695         devs.into_iter()
696             .take(num_devs as usize)
697             .map(CrasIodevInfo::from)
698     }
699 
700     /// Gets a list of output nodes
701     ///
702     /// Read a list of the currently attached output nodes from shared memory.
output_nodes(&self) -> impl Iterator<Item = CrasIonodeInfo>703     pub fn output_nodes(&self) -> impl Iterator<Item = CrasIonodeInfo> {
704         let mut nodes: Vec<cras_ionode_info> = vec![Default::default(); CRAS_MAX_IONODES as usize];
705         let num_nodes = self.synchronized_state_read(|| {
706             self.output_nodes.copy_to(&mut nodes);
707             self.num_output_nodes.load()
708         });
709         nodes
710             .into_iter()
711             .take(num_nodes as usize)
712             .map(CrasIonodeInfo::from)
713     }
714 
715     /// Gets a list of input nodes
716     ///
717     /// Read a list of the currently attached input nodes from shared memory.
input_nodes(&self) -> impl Iterator<Item = CrasIonodeInfo>718     pub fn input_nodes(&self) -> impl Iterator<Item = CrasIonodeInfo> {
719         let mut nodes: Vec<cras_ionode_info> = vec![Default::default(); CRAS_MAX_IONODES as usize];
720         let num_nodes = self.synchronized_state_read(|| {
721             self.input_nodes.copy_to(&mut nodes);
722             self.num_input_nodes.load()
723         });
724         nodes
725             .into_iter()
726             .take(num_nodes as usize)
727             .map(CrasIonodeInfo::from)
728     }
729 
730     /// Get audio debug info
731     ///
732     /// Loads the server's audio_debug_info struct and converts it into an
733     /// idiomatic rust representation.
734     ///
735     /// # Errors
736     /// * If any of the stream debug information structs are invalid.
get_audio_debug_info(&self) -> Result<AudioDebugInfo, cras_sys::Error>737     pub fn get_audio_debug_info(&self) -> Result<AudioDebugInfo, cras_sys::Error> {
738         let mut devs: Vec<audio_dev_debug_info> = vec![Default::default(); MAX_DEBUG_DEVS as usize];
739         let mut streams: Vec<audio_stream_debug_info> =
740             vec![Default::default(); MAX_DEBUG_STREAMS as usize];
741         let (num_devs, num_streams) = self.synchronized_state_read(|| {
742             self.debug_info_devs.copy_to(&mut devs);
743             self.debug_info_streams.copy_to(&mut streams);
744             (
745                 self.debug_info_num_devs.load(),
746                 self.debug_info_num_streams.load(),
747             )
748         });
749         let dev_info = devs
750             .into_iter()
751             .take(num_devs as usize)
752             .map(AudioDevDebugInfo::from)
753             .collect();
754         let stream_info = streams
755             .into_iter()
756             .take(num_streams as usize)
757             .map(AudioStreamDebugInfo::try_from)
758             .collect::<Result<Vec<_>, _>>()?;
759         Ok(AudioDebugInfo::new(dev_info, stream_info))
760     }
761 }
762 
763 impl<'a> Drop for CrasServerState<'a> {
764     /// Call `munmap` for `addr`.
drop(&mut self)765     fn drop(&mut self) {
766         unsafe {
767             // Safe because all references must be gone by the time drop is called.
768             libc::munmap(self.addr, mem::size_of::<cras_server_state>());
769         }
770     }
771 }
772 
773 /// A structure holding the mapped shared memory area used to exchange
774 /// samples with CRAS. The shared memory is owned exclusively by this structure,
775 /// and will be cleaned up on drop.
776 /// * `addr` - The address of the mapped shared memory.
777 /// * `len` - Length of the mapped shared memory in bytes.
778 pub struct CrasAudioBuffer {
779     addr: *mut u8,
780     len: usize,
781 }
782 
783 // It is safe to send audio buffers between threads as this struct has exclusive ownership of the
784 // shared memory area contained in it.
785 unsafe impl Send for CrasAudioBuffer {}
786 
787 impl CrasAudioBuffer {
new(samples_fd: CrasShmFd) -> io::Result<Self>788     fn new(samples_fd: CrasShmFd) -> io::Result<Self> {
789         // This is safe because we checked that the size of the shm in samples_fd
790         // was at least samples_fd.size when it was created.
791         let addr = unsafe {
792             cras_mmap(
793                 samples_fd.size,
794                 libc::PROT_READ | libc::PROT_WRITE,
795                 samples_fd.as_raw_fd(),
796             )? as *mut u8
797         };
798         Ok(Self {
799             addr,
800             len: samples_fd.size,
801         })
802     }
803 
804     /// Provides a mutable slice to be filled with audio samples.
get_buffer(&mut self) -> &mut [u8]805     pub fn get_buffer(&mut self) -> &mut [u8] {
806         // This is safe because it takes a mutable reference to self, and there can only be one
807         // taken at a time. Although this is shared memory, the reader side must have it mapped as
808         // read only.
809         unsafe { slice::from_raw_parts_mut(self.addr, self.len) }
810     }
811 }
812 
813 impl Drop for CrasAudioBuffer {
drop(&mut self)814     fn drop(&mut self) {
815         // Safe because all references must be gone by the time drop is called.
816         unsafe {
817             libc::munmap(self.addr as *mut _, self.len);
818         }
819     }
820 }
821 
822 /// Creates header and buffer from given shared memory fds.
create_header_and_buffers<'a>( header_fd: CrasAudioShmHeaderFd, samples_fd: CrasShmFd, ) -> io::Result<(CrasAudioHeader<'a>, CrasAudioBuffer)>823 pub fn create_header_and_buffers<'a>(
824     header_fd: CrasAudioShmHeaderFd,
825     samples_fd: CrasShmFd,
826 ) -> io::Result<(CrasAudioHeader<'a>, CrasAudioBuffer)> {
827     let header = CrasAudioHeader::new(header_fd, samples_fd.size)?;
828     let buffer = CrasAudioBuffer::new(samples_fd)?;
829 
830     Ok((header, buffer))
831 }
832 
833 /// Creates header from header shared memory fds. Use this function
834 /// when mapping the samples shm is not necessary, for instance with a
835 /// client-provided shm stream.
create_header<'a>( header_fd: CrasAudioShmHeaderFd, samples_len: usize, ) -> io::Result<CrasAudioHeader<'a>>836 pub fn create_header<'a>(
837     header_fd: CrasAudioShmHeaderFd,
838     samples_len: usize,
839 ) -> io::Result<CrasAudioHeader<'a>> {
840     Ok(CrasAudioHeader::new(header_fd, samples_len)?)
841 }
842 
843 /// A structure wrapping a fd which contains a shared memory area and its size.
844 /// * `fd` - The shared memory file descriptor, a `libc::c_int`.
845 /// * `size` - Size of the shared memory area.
846 pub struct CrasShmFd {
847     fd: libc::c_int,
848     size: usize,
849 }
850 
851 impl CrasShmFd {
852     /// Creates a `CrasShmFd` by shared memory fd and size
853     /// # Arguments
854     /// * `fd` - A shared memory file descriptor, which will be owned by the resulting structure and
855     /// the fd will be closed on drop.
856     /// * `size` - Size of the shared memory.
857     ///
858     /// # Returns
859     /// * `CrasShmFd` - Wrap the input arguments without doing anything.
860     ///
861     /// To use this function safely, we need to make sure
862     /// - The input fd is a valid shared memory fd.
863     /// - The input shared memory fd won't be used by others.
864     /// - The input fd contains memory size larger than `size`.
new(fd: libc::c_int, size: usize) -> CrasShmFd865     pub unsafe fn new(fd: libc::c_int, size: usize) -> CrasShmFd {
866         CrasShmFd { fd, size }
867     }
868 }
869 
870 impl AsRawFd for CrasShmFd {
as_raw_fd(&self) -> RawFd871     fn as_raw_fd(&self) -> RawFd {
872         self.fd
873     }
874 }
875 
876 impl Drop for CrasShmFd {
drop(&mut self)877     fn drop(&mut self) {
878         // It's safe here if we make sure
879         // - the input fd is valid and
880         // - `CrasShmFd` is the only owner
881         // in `new` function
882         unsafe {
883             libc::close(self.fd);
884         }
885     }
886 }
887 
888 /// A structure wrapping a fd which contains a shared `cras_server_state`.
889 /// * `shm_fd` - A shared memory fd contains a `cras_server_state`
890 pub struct CrasServerStateShmFd {
891     fd: CrasShmFd,
892 }
893 
894 impl CrasServerStateShmFd {
895     /// Creates a `CrasServerStateShmFd` by shared memory fd
896     /// # Arguments
897     /// * `fd` - A shared memory file descriptor, which will be owned by the resulting structure and
898     /// the fd will be closed on drop.
899     ///
900     /// # Returns
901     /// A structure wrapping a `CrasShmFd` with the input fd and `size` which equals to
902     /// the size of `cras_server_sate`.
903     ///
904     /// To use this function safely, we need to make sure
905     /// - The input fd is a valid shared memory fd.
906     /// - The input shared memory fd won't be used by others.
907     /// - The shared memory area in the input fd contains a `cras_server_state`.
new(fd: libc::c_int) -> Self908     pub unsafe fn new(fd: libc::c_int) -> Self {
909         Self {
910             fd: CrasShmFd::new(fd, mem::size_of::<cras_server_state>()),
911         }
912     }
913 }
914 
915 #[cfg(test)]
916 mod tests {
917     use super::*;
918     use std::fs::File;
919     use std::os::unix::io::IntoRawFd;
920     use std::sync::{Arc, Mutex};
921     use std::thread;
922     use sys_util::{kernel_has_memfd, SharedMemory};
923 
924     #[test]
cras_audio_header_switch_test()925     fn cras_audio_header_switch_test() {
926         if !kernel_has_memfd() {
927             return;
928         }
929         let mut header = create_cras_audio_header(20);
930         assert_eq!(0, header.get_write_buf_idx());
931         header.switch_write_buf_idx();
932         assert_eq!(1, header.get_write_buf_idx());
933     }
934 
935     #[test]
cras_audio_header_write_offset_test()936     fn cras_audio_header_write_offset_test() {
937         if !kernel_has_memfd() {
938             return;
939         }
940         let mut header = create_cras_audio_header(20);
941         header.frame_size.store(2);
942         header.used_size.store(5);
943         header.set_buffer_offset(0, 12).unwrap();
944 
945         assert_eq!(0, header.write_offset[0].load());
946         // Index out of bound
947         assert!(header.set_write_offset(2, 5).is_err());
948         // Offset out of bound
949         // Buffer length is 4, since that's the largest multiple of frame_size
950         // less than used_size.
951         assert!(header.set_write_offset(0, 6).is_err());
952         assert_eq!(0, header.write_offset[0].load());
953         assert!(header.set_write_offset(0, 5).is_err());
954         assert_eq!(0, header.write_offset[0].load());
955         assert!(header.set_write_offset(0, 4).is_ok());
956         assert_eq!(4, header.write_offset[0].load());
957     }
958 
959     #[test]
cras_audio_header_read_offset_test()960     fn cras_audio_header_read_offset_test() {
961         if !kernel_has_memfd() {
962             return;
963         }
964         let mut header = create_cras_audio_header(20);
965         header.frame_size.store(2);
966         header.used_size.store(5);
967         header.set_buffer_offset(0, 12).unwrap();
968 
969         assert_eq!(0, header.read_offset[0].load());
970         // Index out of bound
971         assert!(header.set_read_offset(2, 5).is_err());
972         // Offset out of bound
973         // Buffer length is 4, since that's the largest multiple of frame_size
974         // less than used_size.
975         assert!(header.set_read_offset(0, 6).is_err());
976         assert_eq!(0, header.read_offset[0].load());
977         assert!(header.set_read_offset(0, 5).is_err());
978         assert_eq!(0, header.read_offset[0].load());
979         assert!(header.set_read_offset(0, 4).is_ok());
980         assert_eq!(4, header.read_offset[0].load());
981     }
982 
983     #[test]
cras_audio_header_commit_written_frame_test()984     fn cras_audio_header_commit_written_frame_test() {
985         if !kernel_has_memfd() {
986             return;
987         }
988         let mut header = create_cras_audio_header(20);
989         header.frame_size.store(2);
990         header.used_size.store(10);
991         header.read_offset[0].store(10);
992         header.set_buffer_offset(0, 10).unwrap();
993 
994         assert!(header.commit_written_frames(5).is_ok());
995         assert_eq!(header.write_offset[0].load(), 10);
996         assert_eq!(header.read_offset[0].load(), 0);
997         assert_eq!(header.write_buf_idx.load(), 1);
998     }
999 
1000     #[test]
cras_audio_header_get_readable_frames_test()1001     fn cras_audio_header_get_readable_frames_test() {
1002         if !kernel_has_memfd() {
1003             return;
1004         }
1005         let header = create_cras_audio_header(20);
1006         header.frame_size.store(2);
1007         header.used_size.store(10);
1008         header.read_offset[0].store(2);
1009         header.write_offset[0].store(10);
1010         let frames = header
1011             .get_readable_frames()
1012             .expect("Failed to get readable frames.");
1013         assert_eq!(frames, 4);
1014     }
1015 
1016     #[test]
cras_audio_header_commit_read_frames_test()1017     fn cras_audio_header_commit_read_frames_test() {
1018         if !kernel_has_memfd() {
1019             return;
1020         }
1021         let mut header = create_cras_audio_header(20);
1022         header.frame_size.store(2);
1023         header.used_size.store(10);
1024         header.read_offset[0].store(2);
1025         header.write_offset[0].store(10);
1026         header
1027             .commit_read_frames(3)
1028             .expect("Failed to commit read frames.");
1029         assert_eq!(header.get_read_buf_idx(), 0);
1030         assert_eq!(header.read_offset[0].load(), 8);
1031 
1032         header
1033             .commit_read_frames(1)
1034             .expect("Failed to commit read frames.");
1035         // Read buffer should be switched
1036         assert_eq!(header.get_read_buf_idx(), 1);
1037         assert_eq!(header.read_offset[0].load(), 0);
1038         assert_eq!(header.read_offset[0].load(), 0);
1039     }
1040 
1041     #[test]
cras_audio_header_get_write_offset_and_len()1042     fn cras_audio_header_get_write_offset_and_len() {
1043         if !kernel_has_memfd() {
1044             return;
1045         }
1046         let header = create_cras_audio_header(30);
1047         header.frame_size.store(2);
1048         header.used_size.store(10);
1049         header.write_buf_idx.store(0);
1050         header.read_offset[0].store(0);
1051         header.write_offset[0].store(0);
1052         header.buffer_offset[0].store(0);
1053 
1054         header.read_buf_idx.store(1);
1055         header.read_offset[1].store(0);
1056         header.write_offset[1].store(0);
1057         header.buffer_offset[1].store(10);
1058 
1059         // standard offsets and lens
1060         let (offset, len) = header.get_write_offset_and_len().unwrap();
1061         assert_eq!(offset, 0);
1062         assert_eq!(len, 10);
1063 
1064         header.write_buf_idx.store(1);
1065         header.read_buf_idx.store(0);
1066         let (offset, len) = header.get_write_offset_and_len().unwrap();
1067         assert_eq!(offset, 10);
1068         assert_eq!(len, 10);
1069 
1070         // relocate buffer offsets
1071         header.buffer_offset[1].store(16);
1072         let (offset, len) = header.get_write_offset_and_len().unwrap();
1073         assert_eq!(offset, 16);
1074         assert_eq!(len, 10);
1075 
1076         header.buffer_offset[0].store(5);
1077         header.write_buf_idx.store(0);
1078         let (offset, len) = header.get_write_offset_and_len().unwrap();
1079         assert_eq!(offset, 5);
1080         assert_eq!(len, 10);
1081 
1082         header.write_buf_idx.store(0);
1083         header.buffer_offset[0].store(2);
1084         header.read_buf_idx.store(1);
1085         header.buffer_offset[1].store(10);
1086         let result = header.get_write_offset_and_len();
1087         // Should be an error as write buffer would overrun into other buffer.
1088         assert!(result.is_err());
1089 
1090         header.buffer_offset[0].store(24);
1091         header.buffer_offset[1].store(10);
1092         let (offset, len) = header.get_write_offset_and_len().unwrap();
1093         // Should be ok since we're only running up against the end of samples.
1094         assert_eq!(offset, 24);
1095         assert_eq!(len, 6);
1096 
1097         header.buffer_offset[0].store(25);
1098         let (offset, len) = header.get_write_offset_and_len().unwrap();
1099         // Should be ok, but we'll truncate len to frame_size.
1100         assert_eq!(offset, 25);
1101         assert_eq!(len, 4);
1102 
1103         header.buffer_offset[0].store(29);
1104         let result = header.get_write_offset_and_len();
1105         // Should be an error as buffer is smaller than frame_size.
1106         assert!(result.is_err());
1107     }
1108 
1109     #[test]
cras_audio_header_set_buffer_offset()1110     fn cras_audio_header_set_buffer_offset() {
1111         if !kernel_has_memfd() {
1112             return;
1113         }
1114         let mut header = create_cras_audio_header(30);
1115         header.frame_size.store(2);
1116         header.used_size.store(10);
1117         header.write_buf_idx.store(0);
1118         header.read_offset[0].store(0);
1119         header.write_offset[0].store(0);
1120         header.buffer_offset[0].store(0);
1121 
1122         header.read_buf_idx.store(1);
1123         header.read_offset[1].store(0);
1124         header.write_offset[1].store(0);
1125         header.buffer_offset[1].store(10);
1126 
1127         // Setting buffer_offset to exactly overlap with other buffer is okay
1128         assert!(header.set_buffer_offset(0, 10).is_ok());
1129 
1130         // Setting buffer_offset to partially overlap other buffer is not okay
1131         assert!(header.set_buffer_offset(0, 9).is_err());
1132 
1133         header.buffer_offset[0].store(0);
1134         header.write_offset[1].store(8);
1135         // With samples, it's still an error.
1136         assert!(header.set_buffer_offset(0, 9).is_err());
1137 
1138         // Setting the offset past the end of the other buffer is okay
1139         assert!(header.set_buffer_offset(0, 20).is_ok());
1140 
1141         // Setting buffer offset such that buffer length is less than used_size
1142         // is okay, but only at the end of the samples area.
1143         assert!(header.set_buffer_offset(0, 21).is_ok());
1144         assert!(header.set_buffer_offset(0, 27).is_ok());
1145 
1146         // It's not okay if we get a buffer with length less than frame_size.
1147         assert!(header.set_buffer_offset(0, 29).is_err());
1148         assert!(header.set_buffer_offset(0, 30).is_err());
1149 
1150         // If we try to overlap another buffer with that other buffer at the end,
1151         // it's not okay, unless it's the exact same index.
1152         assert!(header.set_buffer_offset(1, 25).is_err());
1153         assert!(header.set_buffer_offset(1, 27).is_ok());
1154         assert!(header.set_buffer_offset(1, 28).is_err());
1155 
1156         // Setting buffer offset past the end of samples is an error.
1157         assert!(header.set_buffer_offset(0, 33).is_err());
1158     }
1159 
1160     #[test]
create_header_and_buffers_test()1161     fn create_header_and_buffers_test() {
1162         if !kernel_has_memfd() {
1163             return;
1164         }
1165         let header_fd = cras_audio_header_fd();
1166         let samples_fd = cras_audio_samples_fd(20);
1167         let res = create_header_and_buffers(header_fd, samples_fd);
1168         res.expect("Failed to create header and buffer.");
1169     }
1170 
create_shm(size: usize) -> File1171     fn create_shm(size: usize) -> File {
1172         let mut shm = SharedMemory::new(None).expect("failed to create shm");
1173         shm.set_size(size as u64).expect("failed to set shm size");
1174         shm.into()
1175     }
1176 
create_cras_audio_header<'a>(samples_len: usize) -> CrasAudioHeader<'a>1177     fn create_cras_audio_header<'a>(samples_len: usize) -> CrasAudioHeader<'a> {
1178         CrasAudioHeader::new(cras_audio_header_fd(), samples_len).unwrap()
1179     }
1180 
cras_audio_header_fd() -> CrasAudioShmHeaderFd1181     fn cras_audio_header_fd() -> CrasAudioShmHeaderFd {
1182         let size = mem::size_of::<cras_audio_shm_header>();
1183         let shm = create_shm(size);
1184         unsafe { CrasAudioShmHeaderFd::new(shm.into_raw_fd()) }
1185     }
1186 
cras_audio_samples_fd(size: usize) -> CrasShmFd1187     fn cras_audio_samples_fd(size: usize) -> CrasShmFd {
1188         let shm = create_shm(size);
1189         unsafe { CrasShmFd::new(shm.into_raw_fd(), size) }
1190     }
1191 
1192     #[test]
cras_mmap_pass()1193     fn cras_mmap_pass() {
1194         if !kernel_has_memfd() {
1195             return;
1196         }
1197         let shm = create_shm(100);
1198         let rc = unsafe { cras_mmap(10, libc::PROT_READ, shm.as_raw_fd()) };
1199         assert!(rc.is_ok());
1200         unsafe { libc::munmap(rc.unwrap(), 10) };
1201     }
1202 
1203     #[test]
cras_mmap_failed()1204     fn cras_mmap_failed() {
1205         if !kernel_has_memfd() {
1206             return;
1207         }
1208         let rc = unsafe { cras_mmap(10, libc::PROT_READ, -1) };
1209         assert!(rc.is_err());
1210     }
1211 
1212     #[test]
cras_server_state()1213     fn cras_server_state() {
1214         let size = mem::size_of::<cras_server_state>();
1215         let shm = create_shm(size);
1216         unsafe {
1217             let addr = cras_mmap(size, libc::PROT_WRITE, shm.as_raw_fd())
1218                 .expect("failed to mmap state shm");
1219             {
1220                 let state: &mut cras_server_state = &mut *(addr as *mut cras_server_state);
1221                 state.state_version = CRAS_SERVER_STATE_VERSION;
1222                 state.volume = 47;
1223                 state.mute = 1;
1224             }
1225             libc::munmap(addr, size);
1226         };
1227         let state_fd = unsafe { CrasServerStateShmFd::new(shm.into_raw_fd()) };
1228         let state =
1229             CrasServerState::try_new(state_fd).expect("try_new failed for valid server_state fd");
1230         assert_eq!(state.get_system_volume(), 47);
1231         assert_eq!(state.get_system_mute(), true);
1232     }
1233 
1234     #[test]
cras_server_state_old_version()1235     fn cras_server_state_old_version() {
1236         let size = mem::size_of::<cras_server_state>();
1237         let shm = create_shm(size);
1238         unsafe {
1239             let addr = cras_mmap(size, libc::PROT_WRITE, shm.as_raw_fd())
1240                 .expect("failed to mmap state shm");
1241             {
1242                 let state: &mut cras_server_state = &mut *(addr as *mut cras_server_state);
1243                 state.state_version = CRAS_SERVER_STATE_VERSION - 1;
1244                 state.volume = 29;
1245                 state.mute = 0;
1246             }
1247             libc::munmap(addr, size);
1248         };
1249         let state_fd = unsafe { CrasServerStateShmFd::new(shm.into_raw_fd()) };
1250         CrasServerState::try_new(state_fd)
1251             .expect_err("try_new succeeded for invalid state version");
1252     }
1253 
1254     #[test]
cras_server_sync_state_read()1255     fn cras_server_sync_state_read() {
1256         let size = mem::size_of::<cras_server_state>();
1257         let shm = create_shm(size);
1258         let addr = unsafe { cras_mmap(size, libc::PROT_WRITE, shm.as_raw_fd()).unwrap() };
1259         let state: &mut cras_server_state = unsafe { &mut *(addr as *mut cras_server_state) };
1260         state.state_version = CRAS_SERVER_STATE_VERSION;
1261         state.update_count = 14;
1262         state.volume = 12;
1263 
1264         let state_fd = unsafe { CrasServerStateShmFd::new(shm.into_raw_fd()) };
1265         let state_struct = CrasServerState::try_new(state_fd).unwrap();
1266 
1267         // Create a lock so that we can block the reader while we change the
1268         // update_count;
1269         let lock = Arc::new(Mutex::new(()));
1270         let thread_lock = lock.clone();
1271         let reader_thread = {
1272             let _guard = lock.lock().unwrap();
1273 
1274             // Create reader thread that will get the value of volume. Since we
1275             // hold the lock currently, this will block until we release the lock.
1276             let reader_thread = thread::spawn(move || {
1277                 state_struct.synchronized_state_read(|| {
1278                     let _guard = thread_lock.lock().unwrap();
1279                     state_struct.volume.load()
1280                 })
1281             });
1282 
1283             // Update volume and change update count so that the synchronized read
1284             // will not return (odd update count means update in progress).
1285             state.volume = 27;
1286             state.update_count = 15;
1287 
1288             reader_thread
1289         };
1290 
1291         // The lock has been released, but the reader thread should still not
1292         // terminate, because of the update in progress.
1293 
1294         // Yield thread to give reader_thread a chance to get scheduled.
1295         thread::yield_now();
1296         {
1297             let _guard = lock.lock().unwrap();
1298 
1299             // Update volume and change update count to indicate the write has
1300             // finished.
1301             state.volume = 42;
1302             state.update_count = 16;
1303         }
1304 
1305         let read_value = reader_thread.join().unwrap();
1306         assert_eq!(read_value, 42);
1307     }
1308 }
1309