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

View File

@ -307,10 +307,8 @@ impl FdSet {
if len > MAX_FDSET_SIZE {
return Err(LxError::EINVAL);
}
let slice = addr.read_array(len)?;
// 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();
vec0.resize(len, 0);
addr.write_array(&vec0)?;

View File

@ -98,14 +98,14 @@ impl Syscall<'_> {
/// - 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 {
info!("semop: id: {}", id);
let ops = ops.read_array(num_ops)?;
let ops = ops.as_slice(num_ops)?;
let sem_array = self
.linux_process()
.semaphores_get(id)
.ok_or(LxError::EINVAL)?;
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);
if flags.contains(SemFlags::IPC_NOWAIT) {
unimplemented!("Semaphore: semop.IPC_NOWAIT");

View File

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

View File

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

View File

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

View File

@ -42,15 +42,18 @@ impl Syscall<'_> {
"fifo.write: handle={:?}, item_size={}, count={:#x}",
handle_value, elem_size, count
);
if count == 0 {
return Err(ZxError::OUT_OF_RANGE);
if count != 0 {
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.

View File

@ -1,9 +1,9 @@
use {super::*, core::convert::TryFrom};
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(
&self,
handle_value: HandleValue,
@ -33,7 +33,7 @@ impl Syscall<'_> {
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 {
info!("handle.close: handle={:?}", handle);
if handle == INVALID_HANDLE {
@ -44,7 +44,7 @@ impl Syscall<'_> {
Ok(())
}
/// Close a number of handles.
/// Close a number of handles.
pub fn sys_handle_close_many(
&self,
handles: UserInPtr<HandleValue>,
@ -55,19 +55,17 @@ impl Syscall<'_> {
handles, num_handles,
);
let proc = self.thread.proc();
let handles = handles.read_array(num_handles)?;
for handle in handles {
if handle == INVALID_HANDLE {
continue;
for handle in handles.as_slice(num_handles)? {
if *handle != INVALID_HANDLE {
proc.remove_handle(*handle)?;
}
proc.remove_handle(handle)?;
}
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(
&self,
handle_value: HandleValue,

View File

@ -1,8 +1,8 @@
use {super::*, zircon_object::ipc::Socket, zircon_object::ipc::SocketFlags};
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.
pub fn sys_socket_create(
&self,
@ -20,9 +20,9 @@ impl Syscall<'_> {
Ok(())
}
/// Write data to a socket.
///
/// Attempts to write `count: usize` bytes to the socket specified by `handle_value`.
/// Write data to a socket.
///
/// Attempts to write `count: usize` bytes to the socket specified by `handle_value`.
pub fn sys_socket_write(
&self,
handle_value: HandleValue,
@ -35,21 +35,20 @@ impl Syscall<'_> {
"socket.write: socket={:#x?}, options={:#x?}, buffer={:#x?}, size={:#x?}",
handle_value, options, user_bytes, count,
);
if count > 0 && user_bytes.is_null() {
return Err(ZxError::INVALID_ARGS);
if (count == 0 || !user_bytes.is_null()) && options == 0 {
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(
&self,
handle_value: HandleValue,
@ -79,7 +78,7 @@ impl Syscall<'_> {
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 {
let options = SocketFlags::from_bits_truncate(options);
info!(

View File

@ -146,11 +146,10 @@ impl Syscall<'_> {
"thread.write_state: handle={:#x?}, kind={:#x?}, buf=({:#x?}; {:#x?})",
handle, kind, buffer, buffer_size,
);
let proc = self.thread.proc();
let thread = proc.get_object_with_rights::<Thread>(handle, Rights::WRITE)?;
let buf = buffer.read_array(buffer_size)?;
thread.write_state(kind, &buf)?;
Ok(())
self.thread
.proc()
.get_object_with_rights::<Thread>(handle, Rights::WRITE)?
.write_state(kind, buffer.as_slice(buffer_size)?)
}
/// Sets process as critical to job.
@ -304,9 +303,10 @@ impl Syscall<'_> {
JOB_POL_ABSOLUTE => SetPolicyOptions::Absolute,
_ => return Err(ZxError::INVALID_ARGS),
};
let all_policy =
UserInPtr::<BasicPolicy>::from(policy).read_array(count as usize)?;
job.set_policy_basic(policy_option, &all_policy)
job.set_policy_basic(
policy_option,
UserInPtr::from(policy).as_slice(count as usize)?,
)
}
//JOB_POL_BASE_V2 => unimplemented!(),
JOB_POL_TIMER_SLACK => {
@ -357,15 +357,17 @@ impl Syscall<'_> {
mut actual: UserOutPtr<usize>,
) -> ZxResult {
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) {
return Err(ZxError::OUT_OF_RANGE);
}
vmo.write(offset as usize, &buf.read_array(buf_size)?)?;
Ok(())
vmo.write(offset as usize, buf.as_slice(buf_size)?)
}
/// Add execute rights to a VMO.