const LCORE_ID_ANY: c_uint = ::std::u32::MAX;
pub const MaximumLogicalCores: usize = RTE_MAX_LCORE;
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(Serialize, Deserialize)]
pub struct LogicalCore(u32);
impl LogicalCore
{
#[inline(always)]
pub fn count() -> u32
{
unsafe { *rte_eal_get_configuration() }.lcore_count
}
}
impl Default for LogicalCore
{
#[inline(always)]
fn default() -> Self
{
Self::Zero
}
}
impl LogicalCore
{
pub const Zero: LogicalCore = LogicalCore(0);
pub const Any: LogicalCore = LogicalCore(LCORE_ID_ANY);
pub fn online(sysPath: &Path) -> Result<LogicalCoresActive, ListParseError>
{
Self::cpulist(sysPath, "online")
}
pub fn offline(sysPath: &Path) -> Result<LogicalCoresActive, ListParseError>
{
Self::cpulist(sysPath, "offline")
}
pub fn possible(sysPath: &Path) -> Result<LogicalCoresActive, ListParseError>
{
Self::cpulist(sysPath, "possible")
}
pub fn present(sysPath: &Path) -> Result<LogicalCoresActive, ListParseError>
{
Self::cpulist(sysPath, "present")
}
pub fn kernelMaximumCpuIndex(sysPath: &Path) -> io::Result<u32>
{
let filePath = Self::cpusItemSysPath(sysPath, "kernel_max");
readValueFromFile(&filePath)
}
fn cpulist(sysPath: &Path, fileName: &str) -> Result<LogicalCoresActive, ListParseError>
{
let filePath = Self::cpusItemSysPath(sysPath, fileName);
LogicalCoresActive::parseFromFilePath(&filePath)
}
pub fn topologyCoreId(&self, sysPath: &Path) -> io::Result<u64>
{
let filePath = self.topologyFilePath(sysPath, "core_id");
readValueFromFile(&filePath)
}
#[inline(always)]
fn cpusSysPath(sysPath: &Path) -> PathBuf
{
let mut nodesSysPath = PathBuf::from(sysPath);
nodesSysPath.push("devices/system/cpu");
nodesSysPath
}
#[inline(always)]
fn cpusItemSysPath(sysPath: &Path, item: &str) -> PathBuf
{
let mut nodesItemSysPath = Self::cpusSysPath(sysPath);
nodesItemSysPath.push(item);
nodesItemSysPath
}
#[inline(always)]
fn cpuSysPath(&self, sysPath: &Path) -> PathBuf
{
if self.isAny()
{
panic!("Any logical core does not have a cpuSysPath");
}
Self::cpusItemSysPath(sysPath, &format!("cpu{}", self.0))
}
#[inline(always)]
fn topologyFilePath(&self, sysPath: &Path, fileName: &str) -> PathBuf
{
let mut path = self.cpuSysPath(sysPath);
path.push("topology");
path.push(fileName);
path
}
pub fn allLogicalCores(excludeMasterIeOnlySlaves: bool) -> Vec<LogicalCore>
{
let excludeIfLogicalCoreIdentifierMatches = match excludeMasterIeOnlySlaves
{
true => Self::getMaster().0,
false => Self::Any.0,
};
let mut list: Vec<LogicalCore> = Vec::with_capacity(Self::count() as usize);
let mut logicalCoreIdentifier = 0;
while logicalCoreIdentifier < MaximumLogicalCores as u32
{
let logicalPort = LogicalCore(logicalCoreIdentifier);
if likely(logicalCoreIdentifier != excludeIfLogicalCoreIdentifierMatches)
{
if logicalPort.isEnabled()
{
list.push(logicalPort);
}
}
logicalCoreIdentifier += 1;
}
list
}
#[inline(always)]
pub fn as_u32(&self) -> u32
{
self.0
}
#[inline(always)]
pub fn isMaster(&self) -> bool
{
*self == Self::getMaster()
}
#[inline(always)]
pub fn isSlave(&self) -> bool
{
*self != Self::getMaster()
}
#[inline(always)]
pub fn isAny(&self) -> bool
{
*self != Self::Any
}
#[inline(always)]
pub fn current() -> LogicalCore
{
LogicalCore(unsafe { ::dpdk_sys::rust_rte_lcore_id() })
}
#[inline(always)]
pub fn isCurrent(&self) -> bool
{
(unsafe { ::dpdk_sys::rust_rte_lcore_id() }) == self.0
}
#[inline(always)]
pub fn isCurrentMaster() -> bool
{
Self::current() == Self::getMaster()
}
#[inline(always)]
pub fn isCurrentSlave() -> bool
{
Self::current() != Self::getMaster()
}
#[inline(always)]
pub fn isCurrentAny() -> bool
{
Self::current() != Self::Any
}
#[inline(always)]
pub fn optionalNumaSocketId(&self) -> Option<NumaSocketId>
{
NumaSocketId::fromU32(unsafe { lcore_config[self.0 as usize] }.socket_id)
}
#[inline(always)]
pub fn isEnabled(&self) -> bool
{
if self.0 as usize >= MaximumLogicalCores
{
false
}
else
{
unsafe { *rte_eal_get_configuration() }.lcore_role[self.0 as usize] != rte_lcore_role_t::ROLE_OFF
}
}
#[inline(always)]
pub fn isUsedInRunTimeEnvironment(&self) -> bool
{
match unsafe { ::dpdk_sys::rte_eal_lcore_role(self.0) }
{
rte_lcore_role_t::ROLE_RTE => true,
rte_lcore_role_t::ROLE_OFF => false,
}
}
#[inline(always)]
pub fn getMaster() -> LogicalCore
{
LogicalCore(unsafe { *rte_eal_get_configuration() }.master_lcore )
}
}
impl LogicalCore
{
#[inline(always)]
pub fn waitForAllSlaveCoresToEnterWaitState()
{
debug_assert!(Self::isCurrentMaster(), "Can not call this waitForAllSlaveCoresToEnterWaitState() on a slave core");
unsafe { ::dpdk_sys::rte_eal_mp_wait_lcore() };
}
#[inline(always)]
pub fn runOnAllSlaves<C: Callback1<i32>>(callback: &C, alsoRunOnMaster: bool) -> Result<(), ()>
{
debug_assert!(Self::isCurrentMaster(), "Can not call this runOnAllSlaves() on a slave core");
let callMaster = match alsoRunOnMaster
{
true => rte_rmt_call_master_t::CALL_MASTER,
false => rte_rmt_call_master_t::SKIP_MASTER,
};
let result = unsafe { ::dpdk_sys::rte_eal_mp_remote_launch(C::asFunctionPointer(), callback.asFunctionArgument(), callMaster) };
if likely(result == 0)
{
Ok(())
}
else
{
match result
{
NegativeE::EBUSY => Err(()),
_ => panic!("Unexptected error '{}' from rte_eal_mp_remote_launch()", result),
}
}
}
#[inline(always)]
pub fn getState(&self) -> rte_lcore_state_t
{
debug_assert!(Self::isCurrentMaster(), "Can not call this getState() on a slave core");
unsafe { ::dpdk_sys::rte_eal_get_lcore_state(self.0) }
}
#[inline(always)]
pub fn waitForThisSlaveToEnterWaitState(&self) -> i32
{
debug_assert!(Self::isCurrentMaster(), "Can not call this waitForThisSlaveToEnterWaitState() on a slave core");
unsafe { ::dpdk_sys::rte_eal_wait_lcore(self.0) }
}
#[inline(always)]
pub fn runOnSlave<C: MutableCallback1<i32>>(&self, callback: &mut C) -> Result<(), ()>
{
debug_assert!(Self::isCurrentMaster(), "Can not call runOnSlave() on a slave core");
let result = unsafe { ::dpdk_sys::rte_eal_remote_launch(C::asFunctionPointer(), callback.asFunctionArgument(), self.0) };
if likely(result == 0)
{
Ok(())
}
else
{
match result
{
NegativeE::EBUSY => Err(()),
_ => panic!("Unexptected error '{}' from rte_eal_remote_launch()", result),
}
}
}
}