in reverie-util/src/pedigree.rs [100:173]
fn try_from(pedigree: &Pedigree) -> Result<Self, Self::Error> {
// Define mpping of pedigree bits -> PID bits
const MSB_ZERO_BITS: usize = 1;
const TREE_BITS: usize = 16;
const RUN_INDEX_BITS: usize = 4;
const RUN_TYPE_BITS: usize = 1;
const RUN_LENGTH_BITS: usize = 10;
debug_assert!(
MSB_ZERO_BITS + TREE_BITS + RUN_INDEX_BITS + RUN_TYPE_BITS + RUN_LENGTH_BITS
== mem::size_of::<pid_t>() * 8
);
// Trim off any trailing P's from pedigree, i.e. viewing it as
// a sequence of 'P' (parent) and 'C' (child) directions.
let mut sequence = pedigree.raw();
while sequence.len() > 1 && sequence.last() == Some(&false) {
sequence.pop();
}
// Find longest run in pedigree sequence
let (index, len) = longest_run(&sequence);
// Make sure pedigree will fit into the bit encoding
if index >= 2_usize.pow(RUN_INDEX_BITS as u32)
|| len >= 2_usize.pow(RUN_LENGTH_BITS as u32)
|| sequence.len() - len > TREE_BITS
{
Err(Self::Error::new(
io::ErrorKind::Other,
"Pedigree is too large or complex to be deterministically converted into virtual PID.",
))
} else {
// Extract the longest run of bits from pedigree
let mut lower_tree = sequence.split_off(index + len);
let run = sequence.split_off(index);
let mut tree = sequence;
tree.append(&mut lower_tree);
// Construct a BitVec which will be interpreted as a pid_t
let mut vpid_bits: BitVec<Msb0, u32> =
BitVec::with_capacity(mem::size_of::<pid_t>() * 8);
// pid_t is signed, so MSB must always be zero or it will be interpreted as error
// when returned from fork, clone, etc.
vpid_bits.push(false);
// Pack the rest of the bits, using asserts to make sure the bitfield sizing
// is correct. Any errors here are fatal bugs, so assert seems acceptable.
let mut tree_bits: BitVec<Msb0, u32> = BitVec::repeat(false, TREE_BITS - tree.len());
tree_bits.append(&mut tree);
debug_assert!(tree_bits.len() == TREE_BITS);
vpid_bits.append(&mut tree_bits);
let mut run_index_bits = BitVec::<Msb0, u32>::from_element(index as u32);
run_index_bits = run_index_bits.split_off(run_index_bits.len() - RUN_INDEX_BITS);
debug_assert!(run_index_bits.len() == RUN_INDEX_BITS);
vpid_bits.append(&mut run_index_bits);
let mut run_type_bits: BitVec<Msb0, u32> = BitVec::new();
run_type_bits.push(run[0]);
debug_assert!(run_type_bits.len() == RUN_TYPE_BITS);
vpid_bits.append(&mut run_type_bits);
let mut run_length_bits = BitVec::<Msb0, u32>::from_element(len as u32);
run_length_bits = run_length_bits.split_off(run_length_bits.len() - RUN_LENGTH_BITS);
debug_assert!(run_length_bits.len() == RUN_LENGTH_BITS);
vpid_bits.append(&mut run_length_bits);
debug_assert!(vpid_bits.len() == mem::size_of::<pid_t>() * 8);
Ok(Pid::from_raw(vpid_bits.into_vec()[0] as i32))
}
}