refactor: 尽量减少对用户指针传入的数组的拷贝

This commit is contained in:
YdrMaster 2022-03-25 11:36:56 +08:00
parent 5783d60f9b
commit 3cc3374c87
11 changed files with 81 additions and 89 deletions

View File

@ -35,11 +35,9 @@ impl Syscall<'_> {
/// - len number of bytes to write /// - len number of bytes to write
pub fn sys_write(&self, fd: FileDesc, base: UserInPtr<u8>, len: usize) -> SysResult { pub fn sys_write(&self, fd: FileDesc, base: UserInPtr<u8>, len: usize) -> SysResult {
info!("write: fd={:?}, base={:?}, len={:#x}", fd, base, len); info!("write: fd={:?}, base={:?}, len={:#x}", fd, base, len);
let proc = self.linux_process(); self.linux_process()
let buf = base.read_array(len)?; .get_file_like(fd)?
let file_like = proc.get_file_like(fd)?; .write(base.as_slice(len)?)
let len = file_like.write(&buf)?;
Ok(len)
} }
/// read from or write to a file descriptor at a given offset /// read from or write to a file descriptor at a given offset
@ -77,11 +75,9 @@ impl Syscall<'_> {
"pwrite: fd={:?}, base={:?}, len={}, offset={}", "pwrite: fd={:?}, base={:?}, len={}, offset={}",
fd, base, len, offset fd, base, len, offset
); );
let proc = self.linux_process(); self.linux_process()
let buf = base.read_array(len)?; .get_file_like(fd)?
let file_like = proc.get_file_like(fd)?; .write_at(offset, base.as_slice(len)?)
let len = file_like.write_at(offset, &buf)?;
Ok(len)
} }
/// works just like read except that multiple buffers are filled. /// works just like read except that multiple buffers are filled.

View File

@ -307,10 +307,8 @@ impl FdSet {
if len > MAX_FDSET_SIZE { if len > MAX_FDSET_SIZE {
return Err(LxError::EINVAL); return Err(LxError::EINVAL);
} }
let slice = addr.read_array(len)?;
// save the fdset, and clear it // save the fdset, and clear it
let origin = BitVec::from_vec(slice); let origin = BitVec::from_slice(addr.as_slice(len)?).unwrap();
let mut vec0 = Vec::<u32>::new(); let mut vec0 = Vec::<u32>::new();
vec0.resize(len, 0); vec0.resize(len, 0);
addr.write_array(&vec0)?; addr.write_array(&vec0)?;

View File

@ -98,14 +98,14 @@ impl Syscall<'_> {
/// - If `op` is -1, see [`release`](linux_object::sync::Semaphore::release). /// - If `op` is -1, see [`release`](linux_object::sync::Semaphore::release).
pub async fn sys_semop(&self, id: usize, ops: UserInPtr<SemBuf>, num_ops: usize) -> SysResult { pub async fn sys_semop(&self, id: usize, ops: UserInPtr<SemBuf>, num_ops: usize) -> SysResult {
info!("semop: id: {}", id); info!("semop: id: {}", id);
let ops = ops.read_array(num_ops)?; let ops = ops.as_slice(num_ops)?;
let sem_array = self let sem_array = self
.linux_process() .linux_process()
.semaphores_get(id) .semaphores_get(id)
.ok_or(LxError::EINVAL)?; .ok_or(LxError::EINVAL)?;
sem_array.otime(); sem_array.otime();
for &SemBuf { num, op, flags } in ops.iter() { for &SemBuf { num, op, flags } in ops {
let flags = SemFlags::from_bits_truncate(flags); let flags = SemFlags::from_bits_truncate(flags);
if flags.contains(SemFlags::IPC_NOWAIT) { if flags.contains(SemFlags::IPC_NOWAIT) {
unimplemented!("Semaphore: semop.IPC_NOWAIT"); unimplemented!("Semaphore: semop.IPC_NOWAIT");

View File

@ -81,11 +81,10 @@ impl Syscall<'_> {
"sys_setsockopt : sockfd : {:?}, level : {:?}, optname : {:?}, optval : {:?} , optlen : {:?}", "sys_setsockopt : sockfd : {:?}, level : {:?}, optname : {:?}, optval : {:?} , optlen : {:?}",
sockfd, level, optname,optval,optlen sockfd, level, optname,optval,optlen
); );
let proc = self.linux_process(); self.linux_process()
let data = optval.read_array(optlen)?; .get_socket(sockfd.into())?
let socket = proc.get_socket(sockfd.into())?; .lock()
let len = socket.lock().setsockopt(level, optname, &data)?; .setsockopt(level, optname, optval.as_slice(optlen)?)
Ok(len)
} }
/// net setsockopt /// net setsockopt
@ -102,8 +101,6 @@ impl Syscall<'_> {
"sys_sendto : sockfd : {:?}, buffer : {:?}, length : {:?}, flags : {:?} , optlen : {:?}, addrlen : {:?}", "sys_sendto : sockfd : {:?}, buffer : {:?}, length : {:?}, flags : {:?} , optlen : {:?}, addrlen : {:?}",
sockfd,buffer,length,flags,dest_addr,addrlen sockfd,buffer,length,flags,dest_addr,addrlen
); );
let proc = self.linux_process();
let data = buffer.read_array(length)?;
let endpoint = if dest_addr.is_null() { let endpoint = if dest_addr.is_null() {
None None
} else { } else {
@ -111,8 +108,9 @@ impl Syscall<'_> {
let endpoint = sockaddr_to_endpoint(dest_addr.read()?, addrlen)?; let endpoint = sockaddr_to_endpoint(dest_addr.read()?, addrlen)?;
Some(endpoint) Some(endpoint)
}; };
let proc = self.linux_process();
let socket = proc.get_socket(sockfd.into())?; let socket = proc.get_socket(sockfd.into())?;
let len = socket.lock().write(&data, endpoint)?; let len = socket.lock().write(buffer.as_slice(length)?, endpoint)?;
Ok(len) Ok(len)
} }

View File

@ -10,7 +10,7 @@ use {
impl Syscall<'_> { impl Syscall<'_> {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
/// Read/Receive a message from a channel. /// Read/Receive a message from a channel.
pub fn sys_channel_read( pub fn sys_channel_read(
&self, &self,
handle_value: HandleValue, handle_value: HandleValue,
@ -74,7 +74,7 @@ impl Syscall<'_> {
} }
Ok(()) Ok(())
} }
/// Write a message to a channel. /// Write a message to a channel.
pub fn sys_channel_write( pub fn sys_channel_write(
&self, &self,
handle_value: HandleValue, handle_value: HandleValue,
@ -96,9 +96,9 @@ impl Syscall<'_> {
} }
let proc = self.thread.proc(); let proc = self.thread.proc();
let data = user_bytes.read_array(num_bytes as usize)?; let data = user_bytes.read_array(num_bytes as usize)?;
let handles = user_handles.read_array(num_handles as usize)?; let handles = user_handles.as_slice(num_handles as usize)?;
let transfer_self = handles.iter().any(|&handle| handle == handle_value); let transfer_self = handles.iter().any(|&handle| handle == handle_value);
let handles = proc.remove_handles(&handles)?; let handles = proc.remove_handles(handles)?;
if transfer_self { if transfer_self {
return Err(ZxError::NOT_SUPPORTED); return Err(ZxError::NOT_SUPPORTED);
} }
@ -114,7 +114,7 @@ impl Syscall<'_> {
channel.write(MessagePacket { data, handles })?; channel.write(MessagePacket { data, handles })?;
Ok(()) Ok(())
} }
/// Create a new channel. /// Create a new channel.
pub fn sys_channel_create( pub fn sys_channel_create(
&self, &self,
options: u32, options: u32,
@ -134,7 +134,7 @@ impl Syscall<'_> {
Ok(()) Ok(())
} }
/// ///
pub async fn sys_channel_call_noretry( pub async fn sys_channel_call_noretry(
&self, &self,
handle_value: HandleValue, handle_value: HandleValue,
@ -161,8 +161,8 @@ impl Syscall<'_> {
let wr_msg = MessagePacket { let wr_msg = MessagePacket {
data: args.wr_bytes.read_array(args.wr_num_bytes as usize)?, data: args.wr_bytes.read_array(args.wr_num_bytes as usize)?,
handles: { handles: {
let handles = args.wr_handles.read_array(args.wr_num_handles as usize)?; let handles = args.wr_handles.as_slice(args.wr_num_handles as usize)?;
let handles = proc.remove_handles(&handles)?; let handles = proc.remove_handles(handles)?;
for handle in handles.iter() { for handle in handles.iter() {
if !handle.rights.contains(Rights::TRANSFER) { if !handle.rights.contains(Rights::TRANSFER) {
return Err(ZxError::ACCESS_DENIED); return Err(ZxError::ACCESS_DENIED);
@ -211,7 +211,7 @@ impl Syscall<'_> {
Err(ZxError::BAD_STATE) Err(ZxError::BAD_STATE)
} }
} }
/// Write a message to a channel. /// Write a message to a channel.
pub fn sys_channel_write_etc( pub fn sys_channel_write_etc(
&self, &self,
handle: HandleValue, handle: HandleValue,

View File

@ -5,8 +5,7 @@ impl Syscall<'_> {
/// Write debug info to the serial port. /// Write debug info to the serial port.
pub fn sys_debug_write(&self, buf: UserInPtr<u8>, len: usize) -> ZxResult { pub fn sys_debug_write(&self, buf: UserInPtr<u8>, len: usize) -> ZxResult {
info!("debug.write: buf=({:?}; {:#x})", buf, len); info!("debug.write: buf=({:?}; {:#x})", buf, len);
let data = buf.read_array(len)?; kernel_hal::console::console_write_str(buf.as_str(len)?);
kernel_hal::console::console_write_str(core::str::from_utf8(&data).unwrap());
Ok(()) Ok(())
} }

View File

@ -42,15 +42,18 @@ impl Syscall<'_> {
"fifo.write: handle={:?}, item_size={}, count={:#x}", "fifo.write: handle={:?}, item_size={}, count={:#x}",
handle_value, elem_size, count handle_value, elem_size, count
); );
if count == 0 { if count != 0 {
return Err(ZxError::OUT_OF_RANGE); let data = user_bytes.as_slice(count * elem_size)?;
let actual_count = self
.thread
.proc()
.get_object_with_rights::<Fifo>(handle_value, Rights::WRITE)?
.write(elem_size, data, count)?;
actual_count_ptr.write_if_not_null(actual_count)?;
Ok(())
} else {
Err(ZxError::OUT_OF_RANGE)
} }
let proc = self.thread.proc();
let fifo = proc.get_object_with_rights::<Fifo>(handle_value, Rights::WRITE)?;
let data = user_bytes.read_array(count * elem_size)?;
let actual_count = fifo.write(elem_size, &data, count)?;
actual_count_ptr.write_if_not_null(actual_count)?;
Ok(())
} }
/// Read data from a fifo. /// Read data from a fifo.

View File

@ -1,9 +1,9 @@
use {super::*, core::convert::TryFrom}; use {super::*, core::convert::TryFrom};
impl Syscall<'_> { impl Syscall<'_> {
/// Creates a duplicate of handle. /// Creates a duplicate of handle.
/// ///
/// Referring to the same underlying object, with new access rights rights. /// Referring to the same underlying object, with new access rights rights.
pub fn sys_handle_duplicate( pub fn sys_handle_duplicate(
&self, &self,
handle_value: HandleValue, handle_value: HandleValue,
@ -33,7 +33,7 @@ impl Syscall<'_> {
Ok(()) Ok(())
} }
/// Close a handle and reclaim the underlying object if no other handles to it exist. /// Close a handle and reclaim the underlying object if no other handles to it exist.
pub fn sys_handle_close(&self, handle: HandleValue) -> ZxResult { pub fn sys_handle_close(&self, handle: HandleValue) -> ZxResult {
info!("handle.close: handle={:?}", handle); info!("handle.close: handle={:?}", handle);
if handle == INVALID_HANDLE { if handle == INVALID_HANDLE {
@ -44,7 +44,7 @@ impl Syscall<'_> {
Ok(()) Ok(())
} }
/// Close a number of handles. /// Close a number of handles.
pub fn sys_handle_close_many( pub fn sys_handle_close_many(
&self, &self,
handles: UserInPtr<HandleValue>, handles: UserInPtr<HandleValue>,
@ -55,19 +55,17 @@ impl Syscall<'_> {
handles, num_handles, handles, num_handles,
); );
let proc = self.thread.proc(); let proc = self.thread.proc();
let handles = handles.read_array(num_handles)?; for handle in handles.as_slice(num_handles)? {
for handle in handles { if *handle != INVALID_HANDLE {
if handle == INVALID_HANDLE { proc.remove_handle(*handle)?;
continue;
} }
proc.remove_handle(handle)?;
} }
Ok(()) Ok(())
} }
/// Creates a replacement for handle. /// Creates a replacement for handle.
/// ///
/// Referring to the same underlying object, with new access rights rights. /// Referring to the same underlying object, with new access rights rights.
pub fn sys_handle_replace( pub fn sys_handle_replace(
&self, &self,
handle_value: HandleValue, handle_value: HandleValue,

View File

@ -1,8 +1,8 @@
use {super::*, zircon_object::ipc::Socket, zircon_object::ipc::SocketFlags}; use {super::*, zircon_object::ipc::Socket, zircon_object::ipc::SocketFlags};
impl Syscall<'_> { impl Syscall<'_> {
/// Create a socket. /// Create a socket.
/// ///
/// Socket is a connected pair of bidirectional stream transports, that can move only data, and that have a maximum capacity. /// Socket is a connected pair of bidirectional stream transports, that can move only data, and that have a maximum capacity.
pub fn sys_socket_create( pub fn sys_socket_create(
&self, &self,
@ -20,9 +20,9 @@ impl Syscall<'_> {
Ok(()) Ok(())
} }
/// Write data to a socket. /// Write data to a socket.
/// ///
/// Attempts to write `count: usize` bytes to the socket specified by `handle_value`. /// Attempts to write `count: usize` bytes to the socket specified by `handle_value`.
pub fn sys_socket_write( pub fn sys_socket_write(
&self, &self,
handle_value: HandleValue, handle_value: HandleValue,
@ -35,21 +35,20 @@ impl Syscall<'_> {
"socket.write: socket={:#x?}, options={:#x?}, buffer={:#x?}, size={:#x?}", "socket.write: socket={:#x?}, options={:#x?}, buffer={:#x?}, size={:#x?}",
handle_value, options, user_bytes, count, handle_value, options, user_bytes, count,
); );
if count > 0 && user_bytes.is_null() { if (count == 0 || !user_bytes.is_null()) && options == 0 {
return Err(ZxError::INVALID_ARGS); let actual_count = self
.thread
.proc()
.get_object_with_rights::<Socket>(handle_value, Rights::WRITE)?
.write(user_bytes.as_slice(count)?)?;
actual_count_ptr.write_if_not_null(actual_count)?;
Ok(())
} else {
Err(ZxError::INVALID_ARGS)
} }
if options != 0 {
return Err(ZxError::INVALID_ARGS);
}
let proc = self.thread.proc();
let socket = proc.get_object_with_rights::<Socket>(handle_value, Rights::WRITE)?;
let data = user_bytes.read_array(count)?;
let actual_count = socket.write(&data)?;
actual_count_ptr.write_if_not_null(actual_count)?;
Ok(())
} }
/// Read data from a socket. /// Read data from a socket.
pub fn sys_socket_read( pub fn sys_socket_read(
&self, &self,
handle_value: HandleValue, handle_value: HandleValue,
@ -79,7 +78,7 @@ impl Syscall<'_> {
Ok(()) Ok(())
} }
/// Prevent future reading or writing on a socket. /// Prevent future reading or writing on a socket.
pub fn sys_socket_shutdown(&self, socket: HandleValue, options: u32) -> ZxResult { pub fn sys_socket_shutdown(&self, socket: HandleValue, options: u32) -> ZxResult {
let options = SocketFlags::from_bits_truncate(options); let options = SocketFlags::from_bits_truncate(options);
info!( info!(

View File

@ -146,11 +146,10 @@ impl Syscall<'_> {
"thread.write_state: handle={:#x?}, kind={:#x?}, buf=({:#x?}; {:#x?})", "thread.write_state: handle={:#x?}, kind={:#x?}, buf=({:#x?}; {:#x?})",
handle, kind, buffer, buffer_size, handle, kind, buffer, buffer_size,
); );
let proc = self.thread.proc(); self.thread
let thread = proc.get_object_with_rights::<Thread>(handle, Rights::WRITE)?; .proc()
let buf = buffer.read_array(buffer_size)?; .get_object_with_rights::<Thread>(handle, Rights::WRITE)?
thread.write_state(kind, &buf)?; .write_state(kind, buffer.as_slice(buffer_size)?)
Ok(())
} }
/// Sets process as critical to job. /// Sets process as critical to job.
@ -304,9 +303,10 @@ impl Syscall<'_> {
JOB_POL_ABSOLUTE => SetPolicyOptions::Absolute, JOB_POL_ABSOLUTE => SetPolicyOptions::Absolute,
_ => return Err(ZxError::INVALID_ARGS), _ => return Err(ZxError::INVALID_ARGS),
}; };
let all_policy = job.set_policy_basic(
UserInPtr::<BasicPolicy>::from(policy).read_array(count as usize)?; policy_option,
job.set_policy_basic(policy_option, &all_policy) UserInPtr::from(policy).as_slice(count as usize)?,
)
} }
//JOB_POL_BASE_V2 => unimplemented!(), //JOB_POL_BASE_V2 => unimplemented!(),
JOB_POL_TIMER_SLACK => { JOB_POL_TIMER_SLACK => {
@ -357,15 +357,17 @@ impl Syscall<'_> {
mut actual: UserOutPtr<usize>, mut actual: UserOutPtr<usize>,
) -> ZxResult { ) -> ZxResult {
if buffer.is_null() || buffer_size == 0 || buffer_size > MAX_BLOCK { if buffer.is_null() || buffer_size == 0 || buffer_size > MAX_BLOCK {
return Err(ZxError::INVALID_ARGS); Err(ZxError::INVALID_ARGS)
} else {
let len = self
.thread
.proc()
.get_object_with_rights::<Process>(handle_value, Rights::READ | Rights::WRITE)?
.vmar()
.write_memory(vaddr, buffer.as_slice(buffer_size)?)?;
actual.write(len)?;
Ok(())
} }
let proc = self.thread.proc();
let process =
proc.get_object_with_rights::<Process>(handle_value, Rights::READ | Rights::WRITE)?;
let data = buffer.read_array(buffer_size)?;
let len = process.vmar().write_memory(vaddr, &data)?;
actual.write(len)?;
Ok(())
} }
} }

View File

@ -71,8 +71,7 @@ impl Syscall<'_> {
if offset as usize > vmo.len() || buf_size > vmo.len() - (offset as usize) { if offset as usize > vmo.len() || buf_size > vmo.len() - (offset as usize) {
return Err(ZxError::OUT_OF_RANGE); return Err(ZxError::OUT_OF_RANGE);
} }
vmo.write(offset as usize, &buf.read_array(buf_size)?)?; vmo.write(offset as usize, buf.as_slice(buf_size)?)
Ok(())
} }
/// Add execute rights to a VMO. /// Add execute rights to a VMO.