Support zero timeout in sys_select. Improve e1000 driver speed

master
Jiajie Chen 6 years ago
parent 02a40b359b
commit a6bb042bd9

@ -27,6 +27,11 @@ use crate::HEAP_ALLOCATOR;
use super::super::{DeviceType, Driver, NetDriver, DRIVERS, NET_DRIVERS, SOCKET_ACTIVITY};
// At the beginning, all transmit descriptors have there status non-zero,
// so we need to track whether we are using the descriptor for the first time.
// When the descriptors wrap around, we set first_trans to false,
// and lookup status instead for checking whether it is empty.
pub struct E1000 {
header: usize,
size: usize,
@ -116,51 +121,6 @@ impl Driver for E1000Interface {
}
}
impl E1000 {
fn transmit_available(&self) -> bool {
if let None = active_table().get_entry(self.header) {
let mut current_addr = self.header;
while current_addr < self.header + self.size {
active_table().map_if_not_exists(current_addr, current_addr);
current_addr = current_addr + PAGE_SIZE;
}
}
let e1000 =
unsafe { slice::from_raw_parts_mut(self.header as *mut Volatile<u32>, self.size / 4) };
let send_queue_size = PAGE_SIZE / size_of::<E1000SendDesc>();
let send_queue = unsafe {
slice::from_raw_parts_mut(self.send_page as *mut E1000RecvDesc, send_queue_size)
};
let tdt = e1000[E1000_TDT].read();
let index = (tdt as usize) % send_queue_size;
let send_desc = &mut send_queue[index];
return self.first_trans || (*send_desc).status & 1 != 0;
}
fn receive_available(&self) -> bool {
if let None = active_table().get_entry(self.header) {
let mut current_addr = self.header;
while current_addr < self.header + self.size {
active_table().map_if_not_exists(current_addr, current_addr);
current_addr = current_addr + PAGE_SIZE;
}
}
let e1000 =
unsafe { slice::from_raw_parts_mut(self.header as *mut Volatile<u32>, self.size / 4) };
let recv_queue_size = PAGE_SIZE / size_of::<E1000RecvDesc>();
let mut recv_queue = unsafe {
slice::from_raw_parts_mut(self.recv_page as *mut E1000RecvDesc, recv_queue_size)
};
let mut rdt = e1000[E1000_RDT].read();
let index = (rdt as usize + 1) % recv_queue_size;
let recv_desc = &mut recv_queue[index];
return (*recv_desc).status & 1 != 0;
}
}
impl NetDriver for E1000Interface {
fn get_mac(&self) -> EthernetAddress {
self.iface.lock().ethernet_addr()
@ -215,7 +175,7 @@ struct E1000RecvDesc {
special: u8,
}
pub struct E1000RxToken(E1000Driver);
pub struct E1000RxToken(Vec<u8>);
pub struct E1000TxToken(E1000Driver);
impl<'a> phy::Device<'a> for E1000Driver {
@ -224,9 +184,51 @@ impl<'a> phy::Device<'a> for E1000Driver {
fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
let driver = self.0.lock();
if driver.transmit_available() && driver.receive_available() {
// potential racing
Some((E1000RxToken(self.clone()), E1000TxToken(self.clone())))
if let None = active_table().get_entry(driver.header) {
let mut current_addr = driver.header;
while current_addr < driver.header + driver.size {
active_table().map_if_not_exists(current_addr, current_addr);
current_addr = current_addr + PAGE_SIZE;
}
}
let e1000 =
unsafe { slice::from_raw_parts_mut(driver.header as *mut Volatile<u32>, driver.size / 4) };
let send_queue_size = PAGE_SIZE / size_of::<E1000SendDesc>();
let send_queue = unsafe {
slice::from_raw_parts_mut(driver.send_page as *mut E1000SendDesc, send_queue_size)
};
let tdt = e1000[E1000_TDT].read();
let index = (tdt as usize) % send_queue_size;
let send_desc = &mut send_queue[index];
let recv_queue_size = PAGE_SIZE / size_of::<E1000RecvDesc>();
let mut recv_queue = unsafe {
slice::from_raw_parts_mut(driver.recv_page as *mut E1000RecvDesc, recv_queue_size)
};
let mut rdt = e1000[E1000_RDT].read();
let index = (rdt as usize + 1) % recv_queue_size;
let recv_desc = &mut recv_queue[index];
let transmit_avail = driver.first_trans || (*send_desc).status & 1 != 0;
let receive_avail = (*recv_desc).status & 1 != 0;
if transmit_avail && receive_avail {
let buffer = unsafe {
slice::from_raw_parts(
driver.recv_buffers[index] as *const u8,
recv_desc.len as usize,
)
};
recv_desc.status = recv_desc.status & !1;
rdt = (rdt + 1) % recv_queue_size as u32;
e1000[E1000_RDT].write(rdt);
Some((E1000RxToken(buffer.to_vec()), E1000TxToken(self.clone())))
} else {
None
}
@ -234,7 +236,27 @@ impl<'a> phy::Device<'a> for E1000Driver {
fn transmit(&'a mut self) -> Option<Self::TxToken> {
let driver = self.0.lock();
if driver.transmit_available() {
if let None = active_table().get_entry(driver.header) {
let mut current_addr = driver.header;
while current_addr < driver.header + driver.size {
active_table().map_if_not_exists(current_addr, current_addr);
current_addr = current_addr + PAGE_SIZE;
}
}
let e1000 =
unsafe { slice::from_raw_parts_mut(driver.header as *mut Volatile<u32>, driver.size / 4) };
let send_queue_size = PAGE_SIZE / size_of::<E1000SendDesc>();
let send_queue = unsafe {
slice::from_raw_parts_mut(driver.send_page as *mut E1000RecvDesc, send_queue_size)
};
let tdt = e1000[E1000_TDT].read();
let index = (tdt as usize) % send_queue_size;
let send_desc = &mut send_queue[index];
let transmit_avail = driver.first_trans || (*send_desc).status & 1 != 0;
if transmit_avail {
Some(E1000TxToken(self.clone()))
} else {
None
@ -244,7 +266,7 @@ impl<'a> phy::Device<'a> for E1000Driver {
fn capabilities(&self) -> DeviceCapabilities {
let mut caps = DeviceCapabilities::default();
caps.max_transmission_unit = 1536;
caps.max_burst_size = Some(32);
caps.max_burst_size = Some(64);
caps
}
}
@ -254,36 +276,7 @@ impl phy::RxToken for E1000RxToken {
where
F: FnOnce(&[u8]) -> Result<R>,
{
let data = {
let mut driver = (self.0).0.lock();
let e1000 = unsafe {
slice::from_raw_parts_mut(driver.header as *mut Volatile<u32>, driver.size / 4)
};
let recv_queue_size = PAGE_SIZE / size_of::<E1000RecvDesc>();
let mut recv_queue = unsafe {
slice::from_raw_parts_mut(driver.recv_page as *mut E1000RecvDesc, recv_queue_size)
};
let mut rdt = e1000[E1000_RDT].read();
let index = (rdt as usize + 1) % recv_queue_size;
let recv_desc = &mut recv_queue[index];
assert!(recv_desc.status & 1 != 0);
let buffer = unsafe {
slice::from_raw_parts(
driver.recv_buffers[index] as *const u8,
recv_desc.len as usize,
)
};
recv_desc.status = recv_desc.status & !1;
rdt = (rdt + 1) % recv_queue_size as u32;
e1000[E1000_RDT].write(rdt);
buffer
};
let result = f(&data);
result
f(&self.0)
}
}

@ -245,7 +245,13 @@ pub fn sys_select(nfds: usize, read: *mut u32, write: *mut u32, err: *mut u32, t
return Ok(events);
}
if timeout_msecs == 0 {
// no timeout, return now;
return Ok(0);
}
let current_time_ms = crate::trap::uptime_msec();
// infinity check
if timeout_msecs < (1 << 31) && current_time_ms - begin_time_ms > timeout_msecs as usize {
return Ok(0);
}

@ -1 +1 @@
Subproject commit 7db2bd11e523f6c176d8aa278a57e5412bc448fa
Subproject commit bae6866610fc24ca66584c1a5200648d2de7d767
Loading…
Cancel
Save