<commit_before>extern crate itertools;

use std::collections::HashMap;
use itertools::Itertools;

// Symbol[2]	Description	Bases represented
// A	Adenine	A				1
// C	Cytosine		C
// G	Guanine			G
// T	Thymine				T
// U	Uracil				U
// W	Weak	A			T	2
// S	Strong		C	G
// M	aMino	A	C
// K	Keto			G	T
// R	puRine	A		G
// Y	pYrimidine		C		T
// B	not A (B comes after A)		C	G	T	3
// D	not C (D comes after C)	A		G	T
// H	not G (H comes after G)	A	C		T
// V	not T (V comes after T and U)	A	C	G
// N or -	any Nucleotide (not a gap)	A	C	G	T	4
// Z	Zero					0

fn iupac_encoding_for(symbol: char) -> Option<Vec<char>> {
    let iupac_table: HashMap<char, Vec<char>> = vec![('A', vec!['A']),
                                                     ('C', vec!['C']),
                                                     ('G', vec!['G']),
                                                     ('T', vec!['T']),
                                                     ('U', vec!['U']),
                                                     ('W', vec!['A', 'T']),
                                                     ('S', vec!['C', 'G']),
                                                     ('M', vec!['A', 'C']),
                                                     ('K', vec!['G', 'T']),
                                                     ('R', vec!['A', 'G']),
                                                     ('Y', vec!['C', 'T']),
                                                     ('B', vec!['C', 'G', 'T']),
                                                     ('D', vec!['A', 'G', 'T']),
                                                     ('H', vec!['A', 'C', 'T']),
                                                     ('V', vec!['A', 'C', 'G']),
                                                     ('N', vec!['A', 'C', 'G', 'T'])]
        .into_iter()
        .collect();

    if let Some(v) = iupac_table.get(&symbol) {
        Some(v.clone())
    } else {
        None
    }
}

pub struct Codons<'a> {
    codons: HashMap<&'a str, &'a str>,
}

pub fn parse<'a>(codons: Vec<(&'a str, &'a str)>) -> Codons<'a> {
    Codons { codons: codons.into_iter().collect() }
}

impl<'a> Codons<'a> {
    pub fn name_for(&self, symbol: &str) -> Result<&str, String> {
        if symbol.len() < 3 {
            return Err("symbol is too short!".to_owned());
        }
        if symbol.len() > 3 {
            return Err("symbol is too long!".to_owned());
        }

        let mappings = symbol.chars()
            .map(|ch| (ch, iupac_encoding_for(ch)))
            .collect::<Vec<(char, Option<Vec<_>>)>>();

        // validate symbols
        for &(ref ch, ref map) in &mappings {
            if map.is_none() {
                return Err(format!("{} is not a shorthand!", ch));
            }
        }

        let mut it = mappings.into_iter();
        let ((_, s1), (_, s2), (_, s3)) =
            (it.next().unwrap(), it.next().unwrap(), it.next().unwrap());

        let combinations = s1.unwrap()
            .into_iter()
            .cartesian_product(s2.unwrap().into_iter())
            .cartesian_product(s3.unwrap().into_iter());

        let all_combinations: Vec<String> = combinations.into_iter()
            .map(|((s1, s2), s3)| format!("{}{}{}", s1, s2, s3))
            .collect();

        for codon in all_combinations {
            if let Some(&val) = self.codons.get(&*codon) {
                return Ok(val);
            }
        }

        Err("invalid codon found!".to_owned())
    }
}
<commit_msg>Nmaing update toNucleotide Codons exercise<commit_after>extern crate itertools;

use std::collections::HashMap;
use itertools::Itertools;

// Symbol[2]	Description	Bases represented
// A	Adenine	A				1
// C	Cytosine		C
// G	Guanine			G
// T	Thymine				T
// U	Uracil				U
// W	Weak	A			T	2
// S	Strong		C	G
// M	aMino	A	C
// K	Keto			G	T
// R	puRine	A		G
// Y	pYrimidine		C		T
// B	not A (B comes after A)		C	G	T	3
// D	not C (D comes after C)	A		G	T
// H	not G (H comes after G)	A	C		T
// V	not T (V comes after T and U)	A	C	G
// N or -	any Nucleotide (not a gap)	A	C	G	T	4
// Z	Zero					0

fn iupac_encoding_for(symbol: char) -> Option<Vec<char>> {
    let iupac_table: HashMap<char, Vec<char>> = vec![('A', vec!['A']),
                                                     ('C', vec!['C']),
                                                     ('G', vec!['G']),
                                                     ('T', vec!['T']),
                                                     ('U', vec!['U']),
                                                     ('W', vec!['A', 'T']),
                                                     ('S', vec!['C', 'G']),
                                                     ('M', vec!['A', 'C']),
                                                     ('K', vec!['G', 'T']),
                                                     ('R', vec!['A', 'G']),
                                                     ('Y', vec!['C', 'T']),
                                                     ('B', vec!['C', 'G', 'T']),
                                                     ('D', vec!['A', 'G', 'T']),
                                                     ('H', vec!['A', 'C', 'T']),
                                                     ('V', vec!['A', 'C', 'G']),
                                                     ('N', vec!['A', 'C', 'G', 'T'])]
        .into_iter()
        .collect();

    if let Some(v) = iupac_table.get(&symbol) {
        Some(v.clone())
    } else {
        None
    }
}

pub struct Codons<'a> {
    codons: HashMap<&'a str, &'a str>,
}

pub fn parse<'a>(codons: Vec<(&'a str, &'a str)>) -> Codons<'a> {
    Codons { codons: codons.into_iter().collect() }
}

impl<'a> Codons<'a> {
    pub fn name_for(&self, symbol: &str) -> Result<&str, String> {
        if symbol.len() < 3 {
            return Err("symbol is too short!".to_owned());
        }
        if symbol.len() > 3 {
            return Err("symbol is too long!".to_owned());
        }

        let mappings = symbol.chars()
            .map(|ch| (ch, iupac_encoding_for(ch)))
            .collect::<Vec<(char, Option<Vec<_>>)>>();

        // validate symbols
        for &(ref ch, ref map) in &mappings {
            if map.is_none() {
                return Err(format!("{} is not a shorthand!", ch));
            }
        }

        let mut it = mappings.into_iter();
        let ((_, s1), (_, s2), (_, s3)) =
            (it.next().unwrap(), it.next().unwrap(), it.next().unwrap());

        let codon_combinations = s1.unwrap()
            .into_iter()
            .cartesian_product(s2.unwrap().into_iter())
            .cartesian_product(s3.unwrap().into_iter());

        let codon_combinations_vec: Vec<String> = codon_combinations.into_iter()
            .map(|((s1, s2), s3)| format!("{}{}{}", s1, s2, s3))
            .collect();

        for codon in codon_combinations_vec {
            if let Some(&val) = self.codons.get(&*codon) {
                return Ok(val);
            }
        }

        Err("invalid codon found!".to_owned())
    }
}
<|endoftext|>


<commit_before>use rustc_serialize::json::Json;

use query::Query;
use query::parser::{QueryParseContext, QueryParseError, parse as parse_query};

pub fn parse(context: &QueryParseContext, json: &Json) -> Result<Query, QueryParseError> {
    let sub_query = try!(parse_query(context, json));

    Ok(Query::Bool {
        must: vec![
            Query::MatchAll
        ],
        must_not: vec![sub_query],
        should: vec![],
        filter: vec![],
        minimum_should_match: 0,
    })
}

#[cfg(test)]
mod tests {
    use rustc_serialize::json::Json;

    use term::Term;
    use query::{Query, TermMatcher};
    use query::parser::{QueryParseContext, QueryParseError};
    use index::Index;

    use super::parse;

    #[test]
    fn test_not_query() {
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        {
            \"term\": {
                \"test\":  \"foo\"
            }
        }
        ").unwrap());

        assert_eq!(query, Ok(Query::Bool {
            must: vec![
                Query::MatchAll
            ],
            must_not: vec![
                Query::MatchTerm {
                    field: "test".to_string(),
                    term: Term::String("foo".to_string()),
                    matcher: TermMatcher::Exact
                }
            ],
            should: vec![],
            filter: vec![],
            minimum_should_match: 0,
        }))
    }

    #[test]
    fn test_gives_error_for_incorrect_type() {
        // String
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        \"hello\"
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));

        // Array
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        [
            \"foo\"
        ]
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));

        // Integer
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        123
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));

        // Float
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        123.1234
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));
    }
}
<commit_msg>Rewrite not query to not use Bool query<commit_after>use rustc_serialize::json::Json;

use query::Query;
use query::parser::{QueryParseContext, QueryParseError, parse as parse_query};

pub fn parse(context: &QueryParseContext, json: &Json) -> Result<Query, QueryParseError> {
    Ok(Query::NegativeFilter {
        query: Box::new(Query::MatchAll),
        filter: Box::new(try!(parse_query(context, json))),
    })
}

#[cfg(test)]
mod tests {
    use rustc_serialize::json::Json;

    use term::Term;
    use query::{Query, TermMatcher};
    use query::parser::{QueryParseContext, QueryParseError};
    use index::Index;

    use super::parse;

    #[test]
    fn test_not_query() {
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        {
            \"term\": {
                \"test\":  \"foo\"
            }
        }
        ").unwrap());

        assert_eq!(query, Ok(Query::NegativeFilter {
            query: Box::new(Query::MatchAll),
            filter: Box::new(Query::MatchTerm {
                field: "test".to_string(),
                term: Term::String("foo".to_string()),
                matcher: TermMatcher::Exact
            }),
        }))
    }

    #[test]
    fn test_gives_error_for_incorrect_type() {
        // String
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        \"hello\"
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));

        // Array
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        [
            \"foo\"
        ]
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));

        // Integer
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        123
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));

        // Float
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        123.1234
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));
    }
}
<|endoftext|>


<commit_before>use rustc_hir::def_id::LocalDefId;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{self, BasicBlock, Location};
use rustc_middle::ty::TyCtxt;
use rustc_span::Span;

use super::ops;
use super::qualifs::{NeedsDrop, Qualif};
use super::validation::Qualifs;
use super::ConstCx;

/// Returns `true` if we should use the more precise live drop checker that runs after drop
/// elaboration.
pub fn checking_enabled(tcx: TyCtxt<'tcx>) -> bool {
    tcx.features().const_precise_live_drops
}

/// Look for live drops in a const context.
///
/// This is separate from the rest of the const checking logic because it must run after drop
/// elaboration.
pub fn check_live_drops(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &mir::Body<'tcx>) {
    let const_kind = tcx.hir().body_const_context(def_id);
    if const_kind.is_none() {
        return;
    }

    if !checking_enabled(tcx) {
        return;
    }

    let ccx = ConstCx { body, tcx, def_id: def_id, const_kind, param_env: tcx.param_env(def_id) };

    let mut visitor = CheckLiveDrops { ccx: &ccx, qualifs: Qualifs::default() };

    visitor.visit_body(body);
}

struct CheckLiveDrops<'mir, 'tcx> {
    ccx: &'mir ConstCx<'mir, 'tcx>,
    qualifs: Qualifs<'mir, 'tcx>,
}

// So we can access `body` and `tcx`.
impl std::ops::Deref for CheckLiveDrops<'mir, 'tcx> {
    type Target = ConstCx<'mir, 'tcx>;

    fn deref(&self) -> &Self::Target {
        &self.ccx
    }
}

impl CheckLiveDrops<'mir, 'tcx> {
    fn check_live_drop(&self, span: Span) {
        ops::non_const(self.ccx, ops::LiveDrop(None), span);
    }
}

impl Visitor<'tcx> for CheckLiveDrops<'mir, 'tcx> {
    fn visit_basic_block_data(&mut self, bb: BasicBlock, block: &mir::BasicBlockData<'tcx>) {
        trace!("visit_basic_block_data: bb={:?} is_cleanup={:?}", bb, block.is_cleanup);

        // Ignore drop terminators in cleanup blocks.
        if block.is_cleanup {
            return;
        }

        self.super_basic_block_data(bb, block);
    }

    fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Location) {
        trace!("visit_terminator: terminator={:?} location={:?}", terminator, location);

        match &terminator.kind {
            mir::TerminatorKind::Drop { place: dropped_place, .. } => {
                let dropped_ty = dropped_place.ty(self.body, self.tcx).ty;
                if !NeedsDrop::in_any_value_of_ty(self.ccx, dropped_ty) {
                    return;
                }

                if dropped_place.is_indirect() {
                    self.check_live_drop(terminator.source_info.span);
                    return;
                }

                if self.qualifs.needs_drop(self.ccx, dropped_place.local, location) {
                    // Use the span where the dropped local was declared for the error.
                    let span = self.body.local_decls[dropped_place.local].source_info.span;
                    self.check_live_drop(span);
                }
            }

            mir::TerminatorKind::DropAndReplace { .. } => span_bug!(
                terminator.source_info.span,
                "`DropAndReplace` should be removed by drop elaboration",
            ),

            mir::TerminatorKind::Abort
            | mir::TerminatorKind::Call { .. }
            | mir::TerminatorKind::Assert { .. }
            | mir::TerminatorKind::FalseEdge { .. }
            | mir::TerminatorKind::FalseUnwind { .. }
            | mir::TerminatorKind::GeneratorDrop
            | mir::TerminatorKind::Goto { .. }
            | mir::TerminatorKind::InlineAsm { .. }
            | mir::TerminatorKind::Resume
            | mir::TerminatorKind::Return
            | mir::TerminatorKind::SwitchInt { .. }
            | mir::TerminatorKind::Unreachable
            | mir::TerminatorKind::Yield { .. } => {}
        }
    }
}
<commit_msg>nit<commit_after>use rustc_hir::def_id::LocalDefId;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{self, BasicBlock, Location};
use rustc_middle::ty::TyCtxt;
use rustc_span::Span;

use super::ops;
use super::qualifs::{NeedsDrop, Qualif};
use super::validation::Qualifs;
use super::ConstCx;

/// Returns `true` if we should use the more precise live drop checker that runs after drop
/// elaboration.
pub fn checking_enabled(tcx: TyCtxt<'tcx>) -> bool {
    tcx.features().const_precise_live_drops
}

/// Look for live drops in a const context.
///
/// This is separate from the rest of the const checking logic because it must run after drop
/// elaboration.
pub fn check_live_drops(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &mir::Body<'tcx>) {
    let const_kind = tcx.hir().body_const_context(def_id);
    if const_kind.is_none() {
        return;
    }

    if !checking_enabled(tcx) {
        return;
    }

    let ccx = ConstCx { body, tcx, def_id, const_kind, param_env: tcx.param_env(def_id) };

    let mut visitor = CheckLiveDrops { ccx: &ccx, qualifs: Qualifs::default() };

    visitor.visit_body(body);
}

struct CheckLiveDrops<'mir, 'tcx> {
    ccx: &'mir ConstCx<'mir, 'tcx>,
    qualifs: Qualifs<'mir, 'tcx>,
}

// So we can access `body` and `tcx`.
impl std::ops::Deref for CheckLiveDrops<'mir, 'tcx> {
    type Target = ConstCx<'mir, 'tcx>;

    fn deref(&self) -> &Self::Target {
        &self.ccx
    }
}

impl CheckLiveDrops<'mir, 'tcx> {
    fn check_live_drop(&self, span: Span) {
        ops::non_const(self.ccx, ops::LiveDrop(None), span);
    }
}

impl Visitor<'tcx> for CheckLiveDrops<'mir, 'tcx> {
    fn visit_basic_block_data(&mut self, bb: BasicBlock, block: &mir::BasicBlockData<'tcx>) {
        trace!("visit_basic_block_data: bb={:?} is_cleanup={:?}", bb, block.is_cleanup);

        // Ignore drop terminators in cleanup blocks.
        if block.is_cleanup {
            return;
        }

        self.super_basic_block_data(bb, block);
    }

    fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Location) {
        trace!("visit_terminator: terminator={:?} location={:?}", terminator, location);

        match &terminator.kind {
            mir::TerminatorKind::Drop { place: dropped_place, .. } => {
                let dropped_ty = dropped_place.ty(self.body, self.tcx).ty;
                if !NeedsDrop::in_any_value_of_ty(self.ccx, dropped_ty) {
                    return;
                }

                if dropped_place.is_indirect() {
                    self.check_live_drop(terminator.source_info.span);
                    return;
                }

                if self.qualifs.needs_drop(self.ccx, dropped_place.local, location) {
                    // Use the span where the dropped local was declared for the error.
                    let span = self.body.local_decls[dropped_place.local].source_info.span;
                    self.check_live_drop(span);
                }
            }

            mir::TerminatorKind::DropAndReplace { .. } => span_bug!(
                terminator.source_info.span,
                "`DropAndReplace` should be removed by drop elaboration",
            ),

            mir::TerminatorKind::Abort
            | mir::TerminatorKind::Call { .. }
            | mir::TerminatorKind::Assert { .. }
            | mir::TerminatorKind::FalseEdge { .. }
            | mir::TerminatorKind::FalseUnwind { .. }
            | mir::TerminatorKind::GeneratorDrop
            | mir::TerminatorKind::Goto { .. }
            | mir::TerminatorKind::InlineAsm { .. }
            | mir::TerminatorKind::Resume
            | mir::TerminatorKind::Return
            | mir::TerminatorKind::SwitchInt { .. }
            | mir::TerminatorKind::Unreachable
            | mir::TerminatorKind::Yield { .. } => {}
        }
    }
}
<|endoftext|>


<commit_before>use super::Event;
use super::EventsHandler;

/*struct GatherEvents<'a> {
    accumulator : Vec<Event<'a> >,
}

impl<'a> EventsHandler for GatherEvents<'a> {
    fn event(&mut self, e : Event){
        self.accumulator.push(e);
    }
    fn log(&mut self, m : &str) { println!("{}",m)  }
}*/

#[test]
fn element_parse_test_1() {
    let b = &[255];

}
<commit_msg>Add a test for parser<commit_after>use super::*;

macro_rules! ehi {
    ($x:ty, $ctr:ident, $e:ident, $c:block) => {
        impl<'a> EventsHandler for $x {
            fn event(&mut self, $e : Event) {*self.$ctr += 1; $c }
            fn log(&mut self, m : &str) { println!("{}", m); }
        }
    }

}

#[test]
fn element_parse_test_1() {
    let mut ctr = 0;
    struct Q<'a> { ctr: &'a mut i32};
    ehi!(Q<'a>, ctr, e, {
        match e {
            Event::Resync => (),
            _ => panic!("Expected resync"),
        }
    });
    {
        let mut p = super::new(Q{ctr : &mut ctr});
        p.feed_bytes(&[255, 255, 255, 255]);
    }
    assert_eq!(ctr, 1);
}
<|endoftext|>


<commit_before>use crate::thread::Time;
use crate::*;
use rustc_target::abi::{Align, Size};
use std::time::{Instant, SystemTime};

/// Implementation of the SYS_futex syscall.
pub fn futex<'tcx>(
    this: &mut MiriEvalContext<'_, 'tcx>,
    args: &[OpTy<'tcx, Tag>],
    dest: PlaceTy<'tcx, Tag>,
) -> InterpResult<'tcx> {
    // The amount of arguments used depends on the type of futex operation.
    // The full futex syscall takes six arguments (excluding the syscall
    // number), which is also the maximum amount of arguments a linux syscall
    // can take on most architectures.
    // However, not all futex operations use all six arguments. The unused ones
    // may or may not be left out from the `syscall()` call.
    // Therefore we don't use `check_arg_count` here, but only check for the
    // number of arguments to fall within a range.
    if !(4..=7).contains(&args.len()) {
        throw_ub_format!("incorrect number of arguments for futex syscall: got {}, expected between 4 and 7 (inclusive)", args.len());
    }

    // The first three arguments (after the syscall number itself) are the same to all futex operations:
    //     (int *addr, int op, int val).
    // We checked above that these definitely exist.
    //
    // `addr` is used to identify the mutex, but note that not all futex
    // operations actually read from this addres or even require this address
    // to exist. Also, the type of `addr` is not consistent. The API requires
    // it to be a 4-byte aligned pointer, and will use the 4 bytes at the given
    // address as an (atomic) i32. It's not uncommon for `addr` to be passed as
    // another type than `*mut i32`, such as `*const AtomicI32`.
    let addr = this.force_ptr(this.read_scalar(args[1])?.check_init()?)?;
    let op = this.read_scalar(args[2])?.to_i32()?;
    let val = this.read_scalar(args[3])?.to_i32()?;

    let thread = this.get_active_thread();

    let futex_private = this.eval_libc_i32("FUTEX_PRIVATE_FLAG")?;
    let futex_wait = this.eval_libc_i32("FUTEX_WAIT")?;
    let futex_wake = this.eval_libc_i32("FUTEX_WAKE")?;
    let futex_realtime = this.eval_libc_i32("FUTEX_CLOCK_REALTIME")?;

    // FUTEX_PRIVATE enables an optimization that stops it from working across processes.
    // Miri doesn't support that anyway, so we ignore that flag.
    match op & !futex_private {
        // FUTEX_WAIT: (int *addr, int op = FUTEX_WAIT, int val, const timespec *timeout)
        // Blocks the thread if *addr still equals val. Wakes up when FUTEX_WAKE is called on the same address,
        // or *timeout expires. `timeout == null` for an infinite timeout.
        op if op & !futex_realtime == futex_wait => {
            if args.len() < 5 {
                throw_ub_format!("incorrect number of arguments for FUTEX_WAIT syscall: got {}, expected at least 5", args.len());
            }
            let timeout = args[4];
            let timeout_time = if this.is_null(this.read_scalar(timeout)?.check_init()?)? {
                None
            } else {
                let duration = match this.read_timespec(timeout)? {
                    Some(duration) => duration,
                    None => {
                        let einval = this.eval_libc("EINVAL")?;
                        this.set_last_error(einval)?;
                        this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?;
                        return Ok(());
                    }
                };
                Some(if op & futex_realtime != 0 {
                    Time::RealTime(SystemTime::now().checked_add(duration).unwrap())
                } else {
                    Time::Monotonic(Instant::now().checked_add(duration).unwrap())
                })
            };
            // Check the pointer for alignment and validity.
            // Atomic operations are only available for fully aligned values.
            this.memory.check_ptr_access(addr.into(), Size::from_bytes(4), Align::from_bytes(4).unwrap())?;
            // Read an `i32` through the pointer, regardless of any wrapper types (e.g. `AtomicI32`).
            let futex_val = this.memory.get_raw(addr.alloc_id)?.read_scalar(this, addr, Size::from_bytes(4))?.to_i32()?;
            if val == futex_val {
                // The value still matches, so we block the trait make it wait for FUTEX_WAKE.
                this.block_thread(thread);
                this.futex_wait(addr, thread);
                // Succesfully waking up from FUTEX_WAIT always returns zero.
                this.write_scalar(Scalar::from_machine_isize(0, this), dest)?;
                // Register a timeout callback if a timeout was specified.
                // This callback will override the return value when the timeout triggers.
                if let Some(timeout_time) = timeout_time {
                    this.register_timeout_callback(
                        thread,
                        timeout_time,
                        Box::new(move |this| {
                            this.unblock_thread(thread);
                            this.futex_remove_waiter(addr, thread);
                            let etimedout = this.eval_libc("ETIMEDOUT")?;
                            this.set_last_error(etimedout)?;
                            this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?;
                            Ok(())
                        }),
                    );
                }
            } else {
                // The futex value doesn't match the expected value, so we return failure
                // right away without sleeping: -1 and errno set to EAGAIN.
                let eagain = this.eval_libc("EAGAIN")?;
                this.set_last_error(eagain)?;
                this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?;
            }
        }
        // FUTEX_WAKE: (int *addr, int op = FUTEX_WAKE, int val)
        // Wakes at most `val` threads waiting on the futex at `addr`.
        // Returns the amount of threads woken up.
        // Does not access the futex value at *addr.
        op if op == futex_wake => {
            let mut n = 0;
            for _ in 0..val {
                if let Some(thread) = this.futex_wake(addr) {
                    this.unblock_thread(thread);
                    this.unregister_timeout_callback_if_exists(thread);
                    n += 1;
                } else {
                    break;
                }
            }
            this.write_scalar(Scalar::from_machine_isize(n, this), dest)?;
        }
        op => throw_unsup_format!("miri does not support SYS_futex operation {}", op),
    }

    Ok(())
}
<commit_msg>Only allow FUTEX_WAIT with timeout when isoloation is disabled.<commit_after>use crate::thread::Time;
use crate::*;
use rustc_target::abi::{Align, Size};
use std::time::{Instant, SystemTime};

/// Implementation of the SYS_futex syscall.
pub fn futex<'tcx>(
    this: &mut MiriEvalContext<'_, 'tcx>,
    args: &[OpTy<'tcx, Tag>],
    dest: PlaceTy<'tcx, Tag>,
) -> InterpResult<'tcx> {
    // The amount of arguments used depends on the type of futex operation.
    // The full futex syscall takes six arguments (excluding the syscall
    // number), which is also the maximum amount of arguments a linux syscall
    // can take on most architectures.
    // However, not all futex operations use all six arguments. The unused ones
    // may or may not be left out from the `syscall()` call.
    // Therefore we don't use `check_arg_count` here, but only check for the
    // number of arguments to fall within a range.
    if !(4..=7).contains(&args.len()) {
        throw_ub_format!("incorrect number of arguments for futex syscall: got {}, expected between 4 and 7 (inclusive)", args.len());
    }

    // The first three arguments (after the syscall number itself) are the same to all futex operations:
    //     (int *addr, int op, int val).
    // We checked above that these definitely exist.
    //
    // `addr` is used to identify the mutex, but note that not all futex
    // operations actually read from this addres or even require this address
    // to exist. Also, the type of `addr` is not consistent. The API requires
    // it to be a 4-byte aligned pointer, and will use the 4 bytes at the given
    // address as an (atomic) i32. It's not uncommon for `addr` to be passed as
    // another type than `*mut i32`, such as `*const AtomicI32`.
    let addr = this.force_ptr(this.read_scalar(args[1])?.check_init()?)?;
    let op = this.read_scalar(args[2])?.to_i32()?;
    let val = this.read_scalar(args[3])?.to_i32()?;

    let thread = this.get_active_thread();

    let futex_private = this.eval_libc_i32("FUTEX_PRIVATE_FLAG")?;
    let futex_wait = this.eval_libc_i32("FUTEX_WAIT")?;
    let futex_wake = this.eval_libc_i32("FUTEX_WAKE")?;
    let futex_realtime = this.eval_libc_i32("FUTEX_CLOCK_REALTIME")?;

    // FUTEX_PRIVATE enables an optimization that stops it from working across processes.
    // Miri doesn't support that anyway, so we ignore that flag.
    match op & !futex_private {
        // FUTEX_WAIT: (int *addr, int op = FUTEX_WAIT, int val, const timespec *timeout)
        // Blocks the thread if *addr still equals val. Wakes up when FUTEX_WAKE is called on the same address,
        // or *timeout expires. `timeout == null` for an infinite timeout.
        op if op & !futex_realtime == futex_wait => {
            if args.len() < 5 {
                throw_ub_format!("incorrect number of arguments for FUTEX_WAIT syscall: got {}, expected at least 5", args.len());
            }
            let timeout = args[4];
            let timeout_time = if this.is_null(this.read_scalar(timeout)?.check_init()?)? {
                None
            } else {
                let duration = match this.read_timespec(timeout)? {
                    Some(duration) => duration,
                    None => {
                        let einval = this.eval_libc("EINVAL")?;
                        this.set_last_error(einval)?;
                        this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?;
                        return Ok(());
                    }
                };
                this.check_no_isolation("FUTEX_WAIT with timeout")?;
                Some(if op & futex_realtime != 0 {
                    Time::RealTime(SystemTime::now().checked_add(duration).unwrap())
                } else {
                    Time::Monotonic(Instant::now().checked_add(duration).unwrap())
                })
            };
            // Check the pointer for alignment and validity.
            // Atomic operations are only available for fully aligned values.
            this.memory.check_ptr_access(addr.into(), Size::from_bytes(4), Align::from_bytes(4).unwrap())?;
            // Read an `i32` through the pointer, regardless of any wrapper types (e.g. `AtomicI32`).
            let futex_val = this.memory.get_raw(addr.alloc_id)?.read_scalar(this, addr, Size::from_bytes(4))?.to_i32()?;
            if val == futex_val {
                // The value still matches, so we block the trait make it wait for FUTEX_WAKE.
                this.block_thread(thread);
                this.futex_wait(addr, thread);
                // Succesfully waking up from FUTEX_WAIT always returns zero.
                this.write_scalar(Scalar::from_machine_isize(0, this), dest)?;
                // Register a timeout callback if a timeout was specified.
                // This callback will override the return value when the timeout triggers.
                if let Some(timeout_time) = timeout_time {
                    this.register_timeout_callback(
                        thread,
                        timeout_time,
                        Box::new(move |this| {
                            this.unblock_thread(thread);
                            this.futex_remove_waiter(addr, thread);
                            let etimedout = this.eval_libc("ETIMEDOUT")?;
                            this.set_last_error(etimedout)?;
                            this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?;
                            Ok(())
                        }),
                    );
                }
            } else {
                // The futex value doesn't match the expected value, so we return failure
                // right away without sleeping: -1 and errno set to EAGAIN.
                let eagain = this.eval_libc("EAGAIN")?;
                this.set_last_error(eagain)?;
                this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?;
            }
        }
        // FUTEX_WAKE: (int *addr, int op = FUTEX_WAKE, int val)
        // Wakes at most `val` threads waiting on the futex at `addr`.
        // Returns the amount of threads woken up.
        // Does not access the futex value at *addr.
        op if op == futex_wake => {
            let mut n = 0;
            for _ in 0..val {
                if let Some(thread) = this.futex_wake(addr) {
                    this.unblock_thread(thread);
                    this.unregister_timeout_callback_if_exists(thread);
                    n += 1;
                } else {
                    break;
                }
            }
            this.write_scalar(Scalar::from_machine_isize(n, this), dest)?;
        }
        op => throw_unsup_format!("miri does not support SYS_futex operation {}", op),
    }

    Ok(())
}
<|endoftext|>


<commit_before>//! Functions to read and write model specific registers.

use crate::registers::rflags::RFlags;
use crate::structures::gdt::SegmentSelector;
use crate::PrivilegeLevel;
use bit_field::BitField;
use bitflags::bitflags;
use core::convert::TryInto;

/// A model specific register.
#[derive(Debug)]
pub struct Msr(u32);

impl Msr {
    /// Create an instance from a register.
    pub const fn new(reg: u32) -> Msr {
        Msr(reg)
    }
}

/// The Extended Feature Enable Register.
#[derive(Debug)]
pub struct Efer;

/// FS.Base Model Specific Register.
#[derive(Debug)]
pub struct FsBase;

/// GS.Base Model Specific Register.
#[derive(Debug)]
pub struct GsBase;

/// KernelGsBase Model Specific Register.
#[derive(Debug)]
pub struct KernelGsBase;

/// Syscall Register: STAR
#[derive(Debug)]
pub struct Star;

/// Syscall Register: LSTAR
#[derive(Debug)]
pub struct LStar;

/// Syscall Register: SFMASK
#[derive(Debug)]
pub struct SFMask;

impl Efer {
    /// The underlying model specific register.
    pub const MSR: Msr = Msr(0xC0000080);
}

impl FsBase {
    /// The underlying model specific register.
    pub const MSR: Msr = Msr(0xC000_0100);
}

impl GsBase {
    /// The underlying model specific register.
    pub const MSR: Msr = Msr(0xC000_0101);
}

impl KernelGsBase {
    /// The underlying model specific register.
    pub const MSR: Msr = Msr(0xC000_0102);
}

impl Star {
    /// The underlying model specific register.
    pub const MSR: Msr = Msr(0xC000_0081);
}

impl LStar {
    /// The underlying model specific register.
    pub const MSR: Msr = Msr(0xC000_0082);
}

impl SFMask {
    /// The underlying model specific register.
    pub const MSR: Msr = Msr(0xC000_0084);
}

bitflags! {
    /// Flags of the Extended Feature Enable Register.
    pub struct EferFlags: u64 {
        /// Enables the `syscall` and `sysret` instructions.
        const SYSTEM_CALL_EXTENSIONS = 1 << 0;
        /// Activates long mode, requires activating paging.
        const LONG_MODE_ENABLE = 1 << 8;
        /// Indicates that long mode is active.
        const LONG_MODE_ACTIVE = 1 << 10;
        /// Enables the no-execute page-protection feature.
        const NO_EXECUTE_ENABLE = 1 << 11;
        /// Enables SVM extensions.
        const SECURE_VIRTUAL_MACHINE_ENABLE = 1 << 12;
        /// Enable certain limit checks in 64-bit mode.
        const LONG_MODE_SEGMENT_LIMIT_ENABLE = 1 << 13;
        /// Enable the `fxsave` and `fxrstor` instructions to execute faster in 64-bit mode.
        const FAST_FXSAVE_FXRSTOR = 1 << 14;
        /// Changes how the `invlpg` instruction operates on TLB entries of upper-level entries.
        const TRANSLATION_CACHE_EXTENSION = 1 << 15;
    }
}

#[cfg(target_arch = "x86_64")]
mod x86_64 {
    use super::*;
    use crate::addr::VirtAddr;

    impl Msr {
        /// Read 64 bits msr register.
        #[inline]
        pub unsafe fn read(&self) -> u64 {
            #[cfg(feature = "inline_asm")]
            {
                let (high, low): (u32, u32);
                asm!("rdmsr" : "={eax}" (low), "={edx}" (high) : "{ecx}" (self.0) : "memory" : "volatile");
                ((high as u64) << 32) | (low as u64)
            }

            #[cfg(not(feature = "inline_asm"))]
            crate::asm::x86_64_asm_rdmsr(self.0)
        }

        /// Write 64 bits to msr register.
        #[inline]
        pub unsafe fn write(&mut self, value: u64) {
            #[cfg(feature = "inline_asm")]
            {
                let low = value as u32;
                let high = (value >> 32) as u32;
                asm!("wrmsr" :: "{ecx}" (self.0), "{eax}" (low), "{edx}" (high) : "memory" : "volatile" );
            }

            #[cfg(not(feature = "inline_asm"))]
            crate::asm::x86_64_asm_wrmsr(self.0, value);
        }
    }

    impl Efer {
        /// Read the current EFER flags.
        #[inline]
        pub fn read() -> EferFlags {
            EferFlags::from_bits_truncate(Self::read_raw())
        }

        /// Read the current raw EFER flags.
        #[inline]
        pub fn read_raw() -> u64 {
            unsafe { Self::MSR.read() }
        }

        /// Write the EFER flags, preserving reserved values.
        ///
        /// Preserves the value of reserved fields. Unsafe because it's possible to break memory
        /// safety, e.g. by disabling long mode.
        #[inline]
        pub unsafe fn write(flags: EferFlags) {
            let old_value = Self::read_raw();
            let reserved = old_value & !(EferFlags::all().bits());
            let new_value = reserved | flags.bits();

            Self::write_raw(new_value);
        }

        /// Write the EFER flags.
        ///
        /// Does not preserve any bits, including reserved fields. Unsafe because it's possible to
        /// break memory safety, e.g. by disabling long mode.
        #[inline]
        pub unsafe fn write_raw(flags: u64) {
            Self::MSR.write(flags);
        }

        /// Update EFER flags.
        ///
        /// Preserves the value of reserved fields. Unsafe because it's possible to break memory
        /// safety, e.g. by disabling long mode.
        #[inline]
        pub unsafe fn update<F>(f: F)
        where
            F: FnOnce(&mut EferFlags),
        {
            let mut flags = Self::read();
            f(&mut flags);
            Self::write(flags);
        }
    }

    impl FsBase {
        /// Read the current FsBase register.
        #[inline]
        pub fn read() -> VirtAddr {
            VirtAddr::new(unsafe { Self::MSR.read() })
        }

        /// Write a given virtual address to the FS.Base register.
        #[inline]
        pub fn write(address: VirtAddr) {
            unsafe { Self::MSR.write(address.as_u64()) };
        }
    }

    impl GsBase {
        /// Read the current GsBase register.
        #[inline]
        pub fn read() -> VirtAddr {
            VirtAddr::new(unsafe { Self::MSR.read() })
        }

        /// Write a given virtual address to the GS.Base register.
        #[inline]
        pub fn write(address: VirtAddr) {
            unsafe { Self::MSR.write(address.as_u64()) };
        }
    }

    impl KernelGsBase {
        /// Read the current KernelGsBase register.
        #[inline]
        pub fn read() -> VirtAddr {
            VirtAddr::new(unsafe { Self::MSR.read() })
        }

        /// Write a given virtual address to the KernelGsBase register.
        #[inline]
        pub fn write(address: VirtAddr) {
            unsafe { Self::MSR.write(address.as_u64()) };
        }
    }

    impl Star {
        /// Read the Ring 0 and Ring 3 segment bases.
        /// The remaining fields are ignored because they are
        /// not valid for long mode.
        ///
        /// # Returns
        /// - Field 1 (SYSRET): The CS selector is set to this field + 16. SS.Sel is set to
        /// this field + 8. Because SYSRET always returns to CPL 3, the
        /// RPL bits 1:0 should be initialized to 11b.
        /// - Field 2 (SYSCALL): This field is copied directly into CS.Sel. SS.Sel is set to
        ///  this field + 8. Because SYSCALL always switches to CPL 0, the RPL bits
        /// 33:32 should be initialized to 00b.
        #[inline]
        pub fn read_raw() -> (u16, u16) {
            let msr_value = unsafe { Self::MSR.read() };
            let sysret = msr_value.get_bits(48..64);
            let syscall = msr_value.get_bits(32..48);
            (sysret.try_into().unwrap(), syscall.try_into().unwrap())
        }

        /// Read the Ring 0 and Ring 3 segment bases.
        /// Returns
        /// - CS Selector SYSRET
        /// - SS Selector SYSRET
        /// - CS Selector SYSCALL
        /// - SS Selector SYSCALL
        #[inline]
        pub fn read() -> (
            SegmentSelector,
            SegmentSelector,
            SegmentSelector,
            SegmentSelector,
        ) {
            let raw = Self::read_raw();
            return (
                SegmentSelector((raw.0 + 16).try_into().unwrap()),
                SegmentSelector((raw.0 + 8).try_into().unwrap()),
                SegmentSelector((raw.1).try_into().unwrap()),
                SegmentSelector((raw.1 + 8).try_into().unwrap()),
            );
        }

        /// Write the Ring 0 and Ring 3 segment bases.
        /// The remaining fields are ignored because they are
        /// not valid for long mode.
        ///
        /// # Parameters
        /// - sysret: The CS selector is set to this field + 16. SS.Sel is set to
        /// this field + 8. Because SYSRET always returns to CPL 3, the
        /// RPL bits 1:0 should be initialized to 11b.
        /// - syscall: This field is copied directly into CS.Sel. SS.Sel is set to
        ///  this field + 8. Because SYSCALL always switches to CPL 0, the RPL bits
        /// 33:32 should be initialized to 00b.
        ///
        /// # Unsafety
        /// Unsafe because this can cause system instability if passed in the
        /// wrong values for the fields.
        #[inline]
        pub unsafe fn write_raw(sysret: u16, syscall: u16) {
            let mut msr_value = 0u64;
            msr_value.set_bits(48..64, sysret.into());
            msr_value.set_bits(32..48, syscall.into());
            Self::MSR.write(msr_value);
        }

        /// Write the Ring 0 and Ring 3 segment bases.
        /// The remaining fields are ignored because they are
        /// not valid for long mode.
        /// This function will fail if the segment selectors are
        /// not in the correct offset of each other or if the
        /// segment selectors do not have correct privileges.
        pub fn write(
            cs_sysret: SegmentSelector,
            ss_sysret: SegmentSelector,
            cs_syscall: SegmentSelector,
            ss_syscall: SegmentSelector,
        ) -> Result<(), &'static str> {
            if cs_sysret.0 - 16 != ss_sysret.0 - 8 {
                return Err("Sysret CS and SS is not offset by 8.");
            }

            if cs_syscall.0 != ss_syscall.0 - 8 {
                return Err("Syscall CS and SS is not offset by 8.");
            }

            if ss_sysret.rpl() != PrivilegeLevel::Ring3 {
                return Err("Sysret's segment must be a Ring3 segment.");
            }

            if ss_syscall.rpl() != PrivilegeLevel::Ring0 {
                return Err("Syscall's segment must be a Ring0 segment.");
            }

            unsafe { Self::write_raw((ss_sysret.0 - 8).into(), cs_syscall.0.into()) };

            Ok(())
        }
    }

    impl LStar {
        /// Read the current LStar register.
        /// This holds the target RIP of a syscall.
        #[inline]
        pub fn read() -> VirtAddr {
            VirtAddr::new(unsafe { Self::MSR.read() })
        }

        /// Write a given virtual address to the LStar register.
        /// This holds the target RIP of a syscall.
        #[inline]
        pub fn write(address: VirtAddr) {
            unsafe { Self::MSR.write(address.as_u64()) };
        }
    }

    impl SFMask {
        /// Read to the SFMask register.
        /// The SFMASK register is used to specify which RFLAGS bits
        /// are cleared during a SYSCALL. In long mode, SFMASK is used
        /// to specify which RFLAGS bits are cleared when SYSCALL is
        /// executed. If a bit in SFMASK is set to 1, the corresponding
        /// bit in RFLAGS is cleared to 0. If a bit in SFMASK is cleared
        /// to 0, the corresponding rFLAGS bit is not modified.
        #[inline]
        pub fn read() -> RFlags {
            RFlags::from_bits(unsafe { Self::MSR.read() }).unwrap()
        }

        /// Write to the SFMask register.
        /// The SFMASK register is used to specify which RFLAGS bits
        /// are cleared during a SYSCALL. In long mode, SFMASK is used
        /// to specify which RFLAGS bits are cleared when SYSCALL is
        /// executed. If a bit in SFMASK is set to 1, the corresponding
        /// bit in RFLAGS is cleared to 0. If a bit in SFMASK is cleared
        /// to 0, the corresponding rFLAGS bit is not modified.
        #[inline]
        pub fn write(value: RFlags) {
            unsafe { Self::MSR.write(value.bits()) };
        }
    }
}
<commit_msg>long literal lacking separators<commit_after>//! Functions to read and write model specific registers.

use crate::registers::rflags::RFlags;
use crate::structures::gdt::SegmentSelector;
use crate::PrivilegeLevel;
use bit_field::BitField;
use bitflags::bitflags;
use core::convert::TryInto;

/// A model specific register.
#[derive(Debug)]
pub struct Msr(u32);

impl Msr {
    /// Create an instance from a register.
    pub const fn new(reg: u32) -> Msr {
        Msr(reg)
    }
}

/// The Extended Feature Enable Register.
#[derive(Debug)]
pub struct Efer;

/// FS.Base Model Specific Register.
#[derive(Debug)]
pub struct FsBase;

/// GS.Base Model Specific Register.
#[derive(Debug)]
pub struct GsBase;

/// KernelGsBase Model Specific Register.
#[derive(Debug)]
pub struct KernelGsBase;

/// Syscall Register: STAR
#[derive(Debug)]
pub struct Star;

/// Syscall Register: LSTAR
#[derive(Debug)]
pub struct LStar;

/// Syscall Register: SFMASK
#[derive(Debug)]
pub struct SFMask;

impl Efer {
    /// The underlying model specific register.
    pub const MSR: Msr = Msr(0xC000_0080);
}

impl FsBase {
    /// The underlying model specific register.
    pub const MSR: Msr = Msr(0xC000_0100);
}

impl GsBase {
    /// The underlying model specific register.
    pub const MSR: Msr = Msr(0xC000_0101);
}

impl KernelGsBase {
    /// The underlying model specific register.
    pub const MSR: Msr = Msr(0xC000_0102);
}

impl Star {
    /// The underlying model specific register.
    pub const MSR: Msr = Msr(0xC000_0081);
}

impl LStar {
    /// The underlying model specific register.
    pub const MSR: Msr = Msr(0xC000_0082);
}

impl SFMask {
    /// The underlying model specific register.
    pub const MSR: Msr = Msr(0xC000_0084);
}

bitflags! {
    /// Flags of the Extended Feature Enable Register.
    pub struct EferFlags: u64 {
        /// Enables the `syscall` and `sysret` instructions.
        const SYSTEM_CALL_EXTENSIONS = 1 << 0;
        /// Activates long mode, requires activating paging.
        const LONG_MODE_ENABLE = 1 << 8;
        /// Indicates that long mode is active.
        const LONG_MODE_ACTIVE = 1 << 10;
        /// Enables the no-execute page-protection feature.
        const NO_EXECUTE_ENABLE = 1 << 11;
        /// Enables SVM extensions.
        const SECURE_VIRTUAL_MACHINE_ENABLE = 1 << 12;
        /// Enable certain limit checks in 64-bit mode.
        const LONG_MODE_SEGMENT_LIMIT_ENABLE = 1 << 13;
        /// Enable the `fxsave` and `fxrstor` instructions to execute faster in 64-bit mode.
        const FAST_FXSAVE_FXRSTOR = 1 << 14;
        /// Changes how the `invlpg` instruction operates on TLB entries of upper-level entries.
        const TRANSLATION_CACHE_EXTENSION = 1 << 15;
    }
}

#[cfg(target_arch = "x86_64")]
mod x86_64 {
    use super::*;
    use crate::addr::VirtAddr;

    impl Msr {
        /// Read 64 bits msr register.
        #[inline]
        pub unsafe fn read(&self) -> u64 {
            #[cfg(feature = "inline_asm")]
            {
                let (high, low): (u32, u32);
                asm!("rdmsr" : "={eax}" (low), "={edx}" (high) : "{ecx}" (self.0) : "memory" : "volatile");
                ((high as u64) << 32) | (low as u64)
            }

            #[cfg(not(feature = "inline_asm"))]
            crate::asm::x86_64_asm_rdmsr(self.0)
        }

        /// Write 64 bits to msr register.
        #[inline]
        pub unsafe fn write(&mut self, value: u64) {
            #[cfg(feature = "inline_asm")]
            {
                let low = value as u32;
                let high = (value >> 32) as u32;
                asm!("wrmsr" :: "{ecx}" (self.0), "{eax}" (low), "{edx}" (high) : "memory" : "volatile" );
            }

            #[cfg(not(feature = "inline_asm"))]
            crate::asm::x86_64_asm_wrmsr(self.0, value);
        }
    }

    impl Efer {
        /// Read the current EFER flags.
        #[inline]
        pub fn read() -> EferFlags {
            EferFlags::from_bits_truncate(Self::read_raw())
        }

        /// Read the current raw EFER flags.
        #[inline]
        pub fn read_raw() -> u64 {
            unsafe { Self::MSR.read() }
        }

        /// Write the EFER flags, preserving reserved values.
        ///
        /// Preserves the value of reserved fields. Unsafe because it's possible to break memory
        /// safety, e.g. by disabling long mode.
        #[inline]
        pub unsafe fn write(flags: EferFlags) {
            let old_value = Self::read_raw();
            let reserved = old_value & !(EferFlags::all().bits());
            let new_value = reserved | flags.bits();

            Self::write_raw(new_value);
        }

        /// Write the EFER flags.
        ///
        /// Does not preserve any bits, including reserved fields. Unsafe because it's possible to
        /// break memory safety, e.g. by disabling long mode.
        #[inline]
        pub unsafe fn write_raw(flags: u64) {
            Self::MSR.write(flags);
        }

        /// Update EFER flags.
        ///
        /// Preserves the value of reserved fields. Unsafe because it's possible to break memory
        /// safety, e.g. by disabling long mode.
        #[inline]
        pub unsafe fn update<F>(f: F)
        where
            F: FnOnce(&mut EferFlags),
        {
            let mut flags = Self::read();
            f(&mut flags);
            Self::write(flags);
        }
    }

    impl FsBase {
        /// Read the current FsBase register.
        #[inline]
        pub fn read() -> VirtAddr {
            VirtAddr::new(unsafe { Self::MSR.read() })
        }

        /// Write a given virtual address to the FS.Base register.
        #[inline]
        pub fn write(address: VirtAddr) {
            unsafe { Self::MSR.write(address.as_u64()) };
        }
    }

    impl GsBase {
        /// Read the current GsBase register.
        #[inline]
        pub fn read() -> VirtAddr {
            VirtAddr::new(unsafe { Self::MSR.read() })
        }

        /// Write a given virtual address to the GS.Base register.
        #[inline]
        pub fn write(address: VirtAddr) {
            unsafe { Self::MSR.write(address.as_u64()) };
        }
    }

    impl KernelGsBase {
        /// Read the current KernelGsBase register.
        #[inline]
        pub fn read() -> VirtAddr {
            VirtAddr::new(unsafe { Self::MSR.read() })
        }

        /// Write a given virtual address to the KernelGsBase register.
        #[inline]
        pub fn write(address: VirtAddr) {
            unsafe { Self::MSR.write(address.as_u64()) };
        }
    }

    impl Star {
        /// Read the Ring 0 and Ring 3 segment bases.
        /// The remaining fields are ignored because they are
        /// not valid for long mode.
        ///
        /// # Returns
        /// - Field 1 (SYSRET): The CS selector is set to this field + 16. SS.Sel is set to
        /// this field + 8. Because SYSRET always returns to CPL 3, the
        /// RPL bits 1:0 should be initialized to 11b.
        /// - Field 2 (SYSCALL): This field is copied directly into CS.Sel. SS.Sel is set to
        ///  this field + 8. Because SYSCALL always switches to CPL 0, the RPL bits
        /// 33:32 should be initialized to 00b.
        #[inline]
        pub fn read_raw() -> (u16, u16) {
            let msr_value = unsafe { Self::MSR.read() };
            let sysret = msr_value.get_bits(48..64);
            let syscall = msr_value.get_bits(32..48);
            (sysret.try_into().unwrap(), syscall.try_into().unwrap())
        }

        /// Read the Ring 0 and Ring 3 segment bases.
        /// Returns
        /// - CS Selector SYSRET
        /// - SS Selector SYSRET
        /// - CS Selector SYSCALL
        /// - SS Selector SYSCALL
        #[inline]
        pub fn read() -> (
            SegmentSelector,
            SegmentSelector,
            SegmentSelector,
            SegmentSelector,
        ) {
            let raw = Self::read_raw();
            return (
                SegmentSelector((raw.0 + 16).try_into().unwrap()),
                SegmentSelector((raw.0 + 8).try_into().unwrap()),
                SegmentSelector((raw.1).try_into().unwrap()),
                SegmentSelector((raw.1 + 8).try_into().unwrap()),
            );
        }

        /// Write the Ring 0 and Ring 3 segment bases.
        /// The remaining fields are ignored because they are
        /// not valid for long mode.
        ///
        /// # Parameters
        /// - sysret: The CS selector is set to this field + 16. SS.Sel is set to
        /// this field + 8. Because SYSRET always returns to CPL 3, the
        /// RPL bits 1:0 should be initialized to 11b.
        /// - syscall: This field is copied directly into CS.Sel. SS.Sel is set to
        ///  this field + 8. Because SYSCALL always switches to CPL 0, the RPL bits
        /// 33:32 should be initialized to 00b.
        ///
        /// # Unsafety
        /// Unsafe because this can cause system instability if passed in the
        /// wrong values for the fields.
        #[inline]
        pub unsafe fn write_raw(sysret: u16, syscall: u16) {
            let mut msr_value = 0u64;
            msr_value.set_bits(48..64, sysret.into());
            msr_value.set_bits(32..48, syscall.into());
            Self::MSR.write(msr_value);
        }

        /// Write the Ring 0 and Ring 3 segment bases.
        /// The remaining fields are ignored because they are
        /// not valid for long mode.
        /// This function will fail if the segment selectors are
        /// not in the correct offset of each other or if the
        /// segment selectors do not have correct privileges.
        pub fn write(
            cs_sysret: SegmentSelector,
            ss_sysret: SegmentSelector,
            cs_syscall: SegmentSelector,
            ss_syscall: SegmentSelector,
        ) -> Result<(), &'static str> {
            if cs_sysret.0 - 16 != ss_sysret.0 - 8 {
                return Err("Sysret CS and SS is not offset by 8.");
            }

            if cs_syscall.0 != ss_syscall.0 - 8 {
                return Err("Syscall CS and SS is not offset by 8.");
            }

            if ss_sysret.rpl() != PrivilegeLevel::Ring3 {
                return Err("Sysret's segment must be a Ring3 segment.");
            }

            if ss_syscall.rpl() != PrivilegeLevel::Ring0 {
                return Err("Syscall's segment must be a Ring0 segment.");
            }

            unsafe { Self::write_raw((ss_sysret.0 - 8).into(), cs_syscall.0.into()) };

            Ok(())
        }
    }

    impl LStar {
        /// Read the current LStar register.
        /// This holds the target RIP of a syscall.
        #[inline]
        pub fn read() -> VirtAddr {
            VirtAddr::new(unsafe { Self::MSR.read() })
        }

        /// Write a given virtual address to the LStar register.
        /// This holds the target RIP of a syscall.
        #[inline]
        pub fn write(address: VirtAddr) {
            unsafe { Self::MSR.write(address.as_u64()) };
        }
    }

    impl SFMask {
        /// Read to the SFMask register.
        /// The SFMASK register is used to specify which RFLAGS bits
        /// are cleared during a SYSCALL. In long mode, SFMASK is used
        /// to specify which RFLAGS bits are cleared when SYSCALL is
        /// executed. If a bit in SFMASK is set to 1, the corresponding
        /// bit in RFLAGS is cleared to 0. If a bit in SFMASK is cleared
        /// to 0, the corresponding rFLAGS bit is not modified.
        #[inline]
        pub fn read() -> RFlags {
            RFlags::from_bits(unsafe { Self::MSR.read() }).unwrap()
        }

        /// Write to the SFMask register.
        /// The SFMASK register is used to specify which RFLAGS bits
        /// are cleared during a SYSCALL. In long mode, SFMASK is used
        /// to specify which RFLAGS bits are cleared when SYSCALL is
        /// executed. If a bit in SFMASK is set to 1, the corresponding
        /// bit in RFLAGS is cleared to 0. If a bit in SFMASK is cleared
        /// to 0, the corresponding rFLAGS bit is not modified.
        #[inline]
        pub fn write(value: RFlags) {
            unsafe { Self::MSR.write(value.bits()) };
        }
    }
}
<|endoftext|>


<commit_before>use actions_process_list_provides;
use rusqlite::Connection;
use std::collections::HashSet;

fn process_session(conn: &Connection) {}

pub fn process(conn: &Connection, actions: &HashSet<String>) {
    let matcher_session = String::from("session");
    if actions.contains(&matcher_session) {
        process_session(conn);
    }
    let matcher_list_provides = String::from("list-provides");
    if actions.contains(&matcher_list_provides) {
        actions_process_list_provides::process_list_provides(conn);
    }
    let matcher_list_target = String::from("list-target");
    if actions.contains(&matcher_list_target) {
        actions_process_list_provides::process_list_targets(conn);
    }
}
<commit_msg>Add central configuration structure<commit_after>use actions_process_list_provides;
use cfg;
use clap::ArgMatches;
use db;
use rusqlite::Connection;
use std::collections::HashSet;

fn process_session(conn: &Connection) {}

pub fn process(conn: &Connection, rt_cfg: &cfg::Config) {
    let matcher_session = String::from("session");
    if rt_cfg.actions.contains(&cfg::Action::SessionStart) {
        process_session(conn);
    }
    let matcher_list_provides = String::from("list-provides");
    if rt_cfg.actions.contains(&cfg::Action::ListProvides) {
        actions_process_list_provides::process_list_provides(conn);
    }
    let matcher_list_target = String::from("list-target");
    if rt_cfg.actions.contains(&cfg::Action::ListTarget) {
        actions_process_list_provides::process_list_targets(conn);
    }
}

pub fn cfg_process_action_db_connect(fred: &mut cfg::Config) -> Connection {
    match fred.rdbms_connection_uri {
        Some(ref connection_uri) => {
            return db::connect_file(&connection_uri);
        }
        None => {
            return db::connect();
        }
    }
}
<|endoftext|>


<commit_before>use rusqlite::Connection;
use std::collections::HashSet;

fn process_session(conn: &Connection)
{

}

fn process_list_provides(conn: &Connection)
{

}

pub fn process(conn: &Connection,actions : &HashSet<String>) {
    let matcher_session = String::from("session");
    if actions.contains(&matcher_session) {
    	process_session(conn);
    }
    let matcher_list_provides = String::from("list-provides");
    if actions.contains(&matcher_list_provides) {
    	process_list_provides(conn);
    }
}<commit_msg>Whitespace cleanup<commit_after>use rusqlite::Connection;
use std::collections::HashSet;
use actions_process_list_provides;

fn process_session(conn: &Connection) {}

pub fn process(conn: &Connection, actions: &HashSet<String>) {
    let matcher_session = String::from("session");
    if actions.contains(&matcher_session) {
        process_session(conn);
    }
    let matcher_list_provides = String::from("list-provides");
    if actions.contains(&matcher_list_provides) {
        actions_process_list_provides::process_list_provides(conn);
    }
    let matcher_list_target = String::from("list-target");
    if actions.contains(&matcher_list_target) {
        actions_process_list_provides::process_list_targets(conn);
    }
}
<|endoftext|>


<commit_before>use super::common::{
    get_attesting_balance, get_matching_head_attestations, get_matching_target_attestations,
    get_total_active_balance, get_unslashed_attesting_indices,
};
use super::validator_statuses::{TotalBalances, ValidatorStatus, ValidatorStatuses};
use super::{Error, WinningRootHashSet};
use integer_sqrt::IntegerSquareRoot;
use types::*;

/// Use to track the changes to a validators balance.
#[derive(Default, Clone)]
pub struct Delta {
    rewards: u64,
    penalties: u64,
}

impl Delta {
    /// Reward the validator with the `reward`.
    pub fn reward(&mut self, reward: u64) {
        self.rewards += reward;
    }

    /// Penalize the validator with the `penalty`.
    pub fn penalize(&mut self, penalty: u64) {
        self.penalties += penalty;
    }
}

impl std::ops::AddAssign for Delta {
    /// Use wrapping addition as that is how it's defined in the spec.
    fn add_assign(&mut self, other: Delta) {
        self.rewards += other.rewards;
        self.penalties += other.penalties;
    }
}

/// Apply attester and proposer rewards.
///
/// Spec v0.6.1
pub fn process_rewards_and_penalties(
    state: &mut BeaconState,
    validator_statuses: &mut ValidatorStatuses,
    winning_root_for_shards: &WinningRootHashSet,
    spec: &ChainSpec,
) -> Result<(), Error> {
    if state.current_epoch(spec) == spec.genesis_epoch {
        return Ok(());
    }

    // Guard against an out-of-bounds during the validator balance update.
    if validator_statuses.statuses.len() != state.balances.len()
        || validator_statuses.statuses.len() != state.validator_registry.len()
    {
        return Err(Error::ValidatorStatusesInconsistent);
    }

    let mut deltas = vec![Delta::default(); state.balances.len()];

    get_attestation_deltas(&mut deltas, state, &validator_statuses, spec)?;
    get_crosslink_deltas(&mut deltas, state, &validator_statuses, spec)?;

    get_proposer_deltas(
        &mut deltas,
        state,
        validator_statuses,
        winning_root_for_shards,
        spec,
    )?;

    // Apply the deltas, over-flowing but not under-flowing (saturating at 0 instead).
    for (i, delta) in deltas.iter().enumerate() {
        state.balances[i] += delta.rewards;
        state.balances[i] = state.balances[i].saturating_sub(delta.penalties);
    }

    Ok(())
}

/// For each attesting validator, reward the proposer who was first to include their attestation.
///
/// Spec v0.6.1
fn get_proposer_deltas(
    deltas: &mut Vec<Delta>,
    state: &BeaconState,
    validator_statuses: &mut ValidatorStatuses,
    winning_root_for_shards: &WinningRootHashSet,
    spec: &ChainSpec,
) -> Result<(), Error> {
    // Update statuses with the information from winning roots.
    validator_statuses.process_winning_roots(state, winning_root_for_shards, spec)?;

    for validator in &validator_statuses.statuses {
        if validator.is_previous_epoch_attester {
            let inclusion = validator
                .inclusion_info
                .expect("It is a logic error for an attester not to have an inclusion distance.");

            let base_reward = get_base_reward(
                state,
                inclusion.proposer_index,
                validator_statuses.total_balances.current_epoch,
                spec,
            )?;

            if inclusion.proposer_index >= deltas.len() {
                return Err(Error::ValidatorStatusesInconsistent);
            }

            deltas[inclusion.proposer_index].reward(base_reward / spec.proposer_reward_quotient);
        }
    }

    Ok(())
}

/// Apply rewards for participation in attestations during the previous epoch.
///
/// Spec v0.6.1
fn get_attestation_deltas(
    deltas: &mut Vec<Delta>,
    state: &BeaconState,
    validator_statuses: &ValidatorStatuses,
    spec: &ChainSpec,
) -> Result<(), Error> {
    let finality_delay = (state.previous_epoch(spec) - state.finalized_epoch).as_u64();

    for (index, validator) in validator_statuses.statuses.iter().enumerate() {
        let base_reward = get_base_reward(
            state,
            index,
            validator_statuses.total_balances.current_epoch,
            spec,
        )?;

        let delta = get_attestation_delta(
            &validator,
            &validator_statuses.total_balances,
            base_reward,
            finality_delay,
            spec,
        );

        deltas[index] += delta;
    }

    Ok(())
}

/// Determine the delta for a single validator, sans proposer rewards.
///
/// Spec v0.6.1
fn get_attestation_delta(
    validator: &ValidatorStatus,
    total_balances: &TotalBalances,
    base_reward: u64,
    finality_delay: u64,
    spec: &ChainSpec,
) -> Delta {
    let mut delta = Delta::default();

    // Is this validator eligible to be rewarded or penalized?
    // Spec: validator index in `eligible_validator_indices`
    let is_eligible = validator.is_active_in_previous_epoch
        || (validator.is_slashed && !validator.is_withdrawable_in_current_epoch);

    if !is_eligible {
        return delta;
    }

    let total_balance = total_balances.current_epoch;
    let total_attesting_balance = total_balances.previous_epoch_attesters;
    let matching_target_balance = total_balances.previous_epoch_target_attesters;
    let matching_head_balance = total_balances.previous_epoch_head_attesters;

    // Expected FFG source.
    // Spec:
    // - validator index in `get_unslashed_attesting_indices(state, matching_source_attestations)`
    if validator.is_previous_epoch_attester && !validator.is_slashed {
        delta.reward(base_reward * total_attesting_balance / total_balance);
        // Inclusion speed bonus
        let inclusion = validator
            .inclusion_info
            .expect("It is a logic error for an attester not to have an inclusion distance.");
        delta.reward(
            base_reward * spec.min_attestation_inclusion_delay / inclusion.distance.as_u64(),
        );
    } else {
        delta.penalize(base_reward);
    }

    // Expected FFG target.
    // Spec:
    // - validator index in `get_unslashed_attesting_indices(state, matching_target_attestations)`
    if validator.is_previous_epoch_target_attester && !validator.is_slashed {
        delta.reward(base_reward * matching_target_balance / total_balance);
    } else {
        delta.penalize(base_reward);
    }

    // Expected head.
    // Spec:
    // - validator index in `get_unslashed_attesting_indices(state, matching_head_attestations)`
    if validator.is_previous_epoch_head_attester && !validator.is_slashed {
        delta.reward(base_reward * matching_head_balance / total_balance);
    } else {
        delta.penalize(base_reward);
    }

    // Inactivity penalty
    if finality_delay > spec.min_epochs_to_inactivity_penalty {
        // All eligible validators are penalized
        delta.penalize(spec.base_rewards_per_epoch * base_reward);

        // Additionally, all validators whose FFG target didn't match are penalized extra
        if !validator.is_previous_epoch_target_attester {
            delta.penalize(
                validator.current_epoch_effective_balance * finality_delay
                    / spec.inactivity_penalty_quotient,
            );
        }
    }

    // Proposer bonus is handled in `get_proposer_deltas`.
    //
    // This function only computes the delta for a single validator, so it cannot also return a
    // delta for a validator.

    delta
}

/// Calculate the deltas based upon the winning roots for attestations during the previous epoch.
///
/// Spec v0.6.1
fn get_crosslink_deltas(
    deltas: &mut Vec<Delta>,
    state: &BeaconState,
    validator_statuses: &ValidatorStatuses,
    spec: &ChainSpec,
) -> Result<(), Error> {
    for (index, validator) in validator_statuses.statuses.iter().enumerate() {
        let mut delta = Delta::default();

        let base_reward = get_base_reward(
            state,
            index,
            validator_statuses.total_balances.current_epoch,
            spec,
        )?;

        if let Some(ref winning_root) = validator.winning_root_info {
            delta.reward(
                base_reward * winning_root.total_attesting_balance
                    / winning_root.total_committee_balance,
            );
        } else {
            delta.penalize(base_reward);
        }

        deltas[index] += delta;
    }

    Ok(())
}

/// Returns the base reward for some validator.
///
/// Spec v0.6.1
fn get_base_reward(
    state: &BeaconState,
    index: usize,
    // Should be == get_total_active_balance(state, spec)
    total_active_balance: u64,
    spec: &ChainSpec,
) -> Result<u64, BeaconStateError> {
    if total_active_balance == 0 {
        Ok(0)
    } else {
        let adjusted_quotient = total_active_balance.integer_sqrt() / spec.base_reward_quotient;
        Ok(state.get_effective_balance(index, spec)?
            / adjusted_quotient
            / spec.base_rewards_per_epoch)
    }
}
<commit_msg>spec: apply_rewards tweaks<commit_after>use super::validator_statuses::{TotalBalances, ValidatorStatus, ValidatorStatuses};
use super::{Error, WinningRootHashSet};
use integer_sqrt::IntegerSquareRoot;
use types::*;

/// Use to track the changes to a validators balance.
#[derive(Default, Clone)]
pub struct Delta {
    rewards: u64,
    penalties: u64,
}

impl Delta {
    /// Reward the validator with the `reward`.
    pub fn reward(&mut self, reward: u64) {
        self.rewards += reward;
    }

    /// Penalize the validator with the `penalty`.
    pub fn penalize(&mut self, penalty: u64) {
        self.penalties += penalty;
    }
}

impl std::ops::AddAssign for Delta {
    /// Use wrapping addition as that is how it's defined in the spec.
    fn add_assign(&mut self, other: Delta) {
        self.rewards += other.rewards;
        self.penalties += other.penalties;
    }
}

/// Apply attester and proposer rewards.
///
/// Spec v0.6.1
pub fn process_rewards_and_penalties(
    state: &mut BeaconState,
    validator_statuses: &mut ValidatorStatuses,
    winning_root_for_shards: &WinningRootHashSet,
    spec: &ChainSpec,
) -> Result<(), Error> {
    if state.current_epoch(spec) == spec.genesis_epoch {
        return Ok(());
    }

    // Guard against an out-of-bounds during the validator balance update.
    if validator_statuses.statuses.len() != state.balances.len()
        || validator_statuses.statuses.len() != state.validator_registry.len()
    {
        return Err(Error::ValidatorStatusesInconsistent);
    }

    let mut deltas = vec![Delta::default(); state.balances.len()];

    get_attestation_deltas(&mut deltas, state, &validator_statuses, spec)?;
    get_crosslink_deltas(&mut deltas, state, &validator_statuses, spec)?;

    get_proposer_deltas(
        &mut deltas,
        state,
        validator_statuses,
        winning_root_for_shards,
        spec,
    )?;

    // Apply the deltas, over-flowing but not under-flowing (saturating at 0 instead).
    for (i, delta) in deltas.iter().enumerate() {
        state.balances[i] += delta.rewards;
        state.balances[i] = state.balances[i].saturating_sub(delta.penalties);
    }

    Ok(())
}

/// For each attesting validator, reward the proposer who was first to include their attestation.
///
/// Spec v0.6.1
fn get_proposer_deltas(
    deltas: &mut Vec<Delta>,
    state: &BeaconState,
    validator_statuses: &mut ValidatorStatuses,
    winning_root_for_shards: &WinningRootHashSet,
    spec: &ChainSpec,
) -> Result<(), Error> {
    // Update statuses with the information from winning roots.
    validator_statuses.process_winning_roots(state, winning_root_for_shards, spec)?;

    for validator in &validator_statuses.statuses {
        if validator.is_previous_epoch_attester {
            let inclusion = validator
                .inclusion_info
                .expect("It is a logic error for an attester not to have an inclusion distance.");

            let base_reward = get_base_reward(
                state,
                inclusion.proposer_index,
                validator_statuses.total_balances.current_epoch,
                spec,
            )?;

            if inclusion.proposer_index >= deltas.len() {
                return Err(Error::ValidatorStatusesInconsistent);
            }

            deltas[inclusion.proposer_index].reward(base_reward / spec.proposer_reward_quotient);
        }
    }

    Ok(())
}

/// Apply rewards for participation in attestations during the previous epoch.
///
/// Spec v0.6.1
fn get_attestation_deltas(
    deltas: &mut Vec<Delta>,
    state: &BeaconState,
    validator_statuses: &ValidatorStatuses,
    spec: &ChainSpec,
) -> Result<(), Error> {
    let finality_delay = (state.previous_epoch(spec) - state.finalized_epoch).as_u64();

    for (index, validator) in validator_statuses.statuses.iter().enumerate() {
        let base_reward = get_base_reward(
            state,
            index,
            validator_statuses.total_balances.current_epoch,
            spec,
        )?;

        let delta = get_attestation_delta(
            &validator,
            &validator_statuses.total_balances,
            base_reward,
            finality_delay,
            spec,
        );

        deltas[index] += delta;
    }

    Ok(())
}

/// Determine the delta for a single validator, sans proposer rewards.
///
/// Spec v0.6.1
fn get_attestation_delta(
    validator: &ValidatorStatus,
    total_balances: &TotalBalances,
    base_reward: u64,
    finality_delay: u64,
    spec: &ChainSpec,
) -> Delta {
    let mut delta = Delta::default();

    // Is this validator eligible to be rewarded or penalized?
    // Spec: validator index in `eligible_validator_indices`
    let is_eligible = validator.is_active_in_previous_epoch
        || (validator.is_slashed && !validator.is_withdrawable_in_current_epoch);

    if !is_eligible {
        return delta;
    }

    let total_balance = total_balances.current_epoch;
    let total_attesting_balance = total_balances.previous_epoch_attesters;
    let matching_target_balance = total_balances.previous_epoch_target_attesters;
    let matching_head_balance = total_balances.previous_epoch_head_attesters;

    // Expected FFG source.
    // Spec:
    // - validator index in `get_unslashed_attesting_indices(state, matching_source_attestations)`
    if validator.is_previous_epoch_attester && !validator.is_slashed {
        delta.reward(base_reward * total_attesting_balance / total_balance);
        // Inclusion speed bonus
        let inclusion = validator
            .inclusion_info
            .expect("It is a logic error for an attester not to have an inclusion distance.");
        delta.reward(base_reward * spec.min_attestation_inclusion_delay / inclusion.distance);
    } else {
        delta.penalize(base_reward);
    }

    // Expected FFG target.
    // Spec:
    // - validator index in `get_unslashed_attesting_indices(state, matching_target_attestations)`
    if validator.is_previous_epoch_target_attester && !validator.is_slashed {
        delta.reward(base_reward * matching_target_balance / total_balance);
    } else {
        delta.penalize(base_reward);
    }

    // Expected head.
    // Spec:
    // - validator index in `get_unslashed_attesting_indices(state, matching_head_attestations)`
    if validator.is_previous_epoch_head_attester && !validator.is_slashed {
        delta.reward(base_reward * matching_head_balance / total_balance);
    } else {
        delta.penalize(base_reward);
    }

    // Inactivity penalty
    if finality_delay > spec.min_epochs_to_inactivity_penalty {
        // All eligible validators are penalized
        delta.penalize(spec.base_rewards_per_epoch * base_reward);

        // Additionally, all validators whose FFG target didn't match are penalized extra
        if !validator.is_previous_epoch_target_attester {
            delta.penalize(
                validator.current_epoch_effective_balance * finality_delay
                    / spec.inactivity_penalty_quotient,
            );
        }
    }

    // Proposer bonus is handled in `get_proposer_deltas`.
    //
    // This function only computes the delta for a single validator, so it cannot also return a
    // delta for a validator.

    delta
}

/// Calculate the deltas based upon the winning roots for attestations during the previous epoch.
///
/// Spec v0.6.1
fn get_crosslink_deltas(
    deltas: &mut Vec<Delta>,
    state: &BeaconState,
    validator_statuses: &ValidatorStatuses,
    spec: &ChainSpec,
) -> Result<(), Error> {
    for (index, validator) in validator_statuses.statuses.iter().enumerate() {
        let mut delta = Delta::default();

        let base_reward = get_base_reward(
            state,
            index,
            validator_statuses.total_balances.current_epoch,
            spec,
        )?;

        if let Some(ref winning_root) = validator.winning_root_info {
            delta.reward(
                base_reward * winning_root.total_attesting_balance
                    / winning_root.total_committee_balance,
            );
        } else {
            delta.penalize(base_reward);
        }

        deltas[index] += delta;
    }

    Ok(())
}

/// Returns the base reward for some validator.
///
/// Spec v0.6.1
fn get_base_reward(
    state: &BeaconState,
    index: usize,
    // Should be == get_total_active_balance(state, spec)
    total_active_balance: u64,
    spec: &ChainSpec,
) -> Result<u64, BeaconStateError> {
    if total_active_balance == 0 {
        Ok(0)
    } else {
        let adjusted_quotient = total_active_balance.integer_sqrt() / spec.base_reward_quotient;
        Ok(state.get_effective_balance(index, spec)?
            / adjusted_quotient
            / spec.base_rewards_per_epoch)
    }
}
<|endoftext|>


<commit_before>#![feature(custom_derive, plugin, libc, rustc_macro)]
#[macro_use] extern crate nom;
#[macro_use] extern crate log;
#[macro_use] extern crate clap;
#[macro_use] extern crate serde_derive;
extern crate env_logger;
extern crate mio;
extern crate yxorp;
extern crate toml;
extern crate rustc_serialize;
extern crate serde;
extern crate serde_json;
extern crate time;
extern crate libc;

mod config;
mod command;
mod state;

use std::net::{UdpSocket,ToSocketAddrs};
use std::sync::mpsc::{channel};
use std::collections::HashMap;
use std::thread::JoinHandle;
use std::env;
use yxorp::network;
use yxorp::network::metrics::{METRICS,ProxyMetrics};
use log::{LogRecord,LogLevelFilter,LogLevel};
use env_logger::LogBuilder;
use clap::{App,Arg};

use command::{Listener,ListenerType};

fn main() {
  let pid = unsafe { libc::getpid() };
  let format = move |record: &LogRecord| {
    match record.level() {
    LogLevel::Debug | LogLevel::Trace => format!("{}\t{}\t{}\t{}\t{}\t|\t{}",
      time::now_utc().rfc3339(), time::precise_time_ns(), pid,
      record.level(), record.args(), record.location().module_path()),
    _ => format!("{}\t{}\t{}\t{}\t{}",
      time::now_utc().rfc3339(), time::precise_time_ns(), pid,
      record.level(), record.args())

    }
  };

  let mut builder = LogBuilder::new();
  builder.format(format).filter(None, LogLevelFilter::Info);

  let matches = App::new("I will not name this thing yxorp")
                        .version(crate_version!())
                        .about("hot reconfigurable proxy")
                        .arg(Arg::with_name("config")
                                    .short("c")
                                    .long("config")
                                    .value_name("FILE")
                                    .help("Sets a custom config file")
                                    .takes_value(true)
                                    .required(true))
                        .get_matches();

  let config_file = matches.value_of("config").unwrap();

  if let Ok(config) = config::Config::load_from_path(config_file) {
    if let Some(log_level) = config.log_level {
     builder.parse(&log_level);
    }

    builder.init().unwrap();
    info!("starting up");

    let metrics_socket = UdpSocket::bind("0.0.0.0:0").unwrap();
    let metrics_host   = (&config.metrics.address[..], config.metrics.port).to_socket_addrs().unwrap().next().unwrap();
    METRICS.lock().unwrap().set_up_remote(metrics_socket, metrics_host);
    let metrics_guard = ProxyMetrics::run();

    let mut listeners = HashMap::new();
    let mut jh_opt: Option<JoinHandle<()>> = None;

    for (ref tag, ref ls) in config.listeners {

      let jg = match ls.listener_type {
        ListenerType::HTTP => {
          //FIXME: make safer
          let conf = ls.to_http().unwrap();
          for _ in 1..ls.worker_count.unwrap_or(1) {
            let (sender, receiver) = channel::<network::ServerMessage>();
            let (tx, _) = network::http::start_listener(conf.clone(), sender);
            let l =  Listener::new(tag.clone(), ls.listener_type, ls.address.clone(), tx, receiver);
            listeners.insert(tag.clone(), l);
          }
          let (sender, receiver) = channel::<network::ServerMessage>();
          //FIXME: keep this to get a join guard
          let (tx, jg) = network::http::start_listener(conf, sender);
          let l =  Listener::new(tag.clone(), ls.listener_type, ls.address.clone(), tx, receiver);
          listeners.insert(tag.clone(), l);
          jg
        },
        ListenerType::HTTPS => {
          let conf = ls.to_tls().unwrap();
          for _ in 1..ls.worker_count.unwrap_or(1) {
            let (sender, receiver) = channel::<network::ServerMessage>();
            let (tx, _) = network::tls::start_listener(conf.clone(), sender);
            let l =  Listener::new(tag.clone(), ls.listener_type, ls.address.clone(), tx, receiver);
            listeners.insert(tag.clone(), l);
          }
          let (sender, receiver) = channel::<network::ServerMessage>();
          //FIXME: keep this to get a join guard
          let (tx, jg) = network::tls::start_listener(conf, sender);
          let l =  Listener::new(tag.clone(), ls.listener_type, ls.address.clone(), tx, receiver);
          listeners.insert(tag.clone(), l);
          jg
        },
        _ => unimplemented!()
      };
      jh_opt = Some(jg);
    };

    let buffer_size     = config.command_buffer_size.unwrap_or(10000);
    let max_buffer_size = config.max_command_buffer_size.unwrap_or(buffer_size * 2);
    command::start(config.command_socket, listeners, config.saved_state, buffer_size, max_buffer_size);
    //FIXME: really join on all threads?
    if let Some(jh) = jh_opt {
      let _ = jh.join();
      info!("good bye");
    }
  } else {
    println!("could not load configuration file at '{}', stopping", config_file);
  }
}

<commit_msg>create threads outside of proxy library<commit_after>#![feature(custom_derive, plugin, libc, rustc_macro)]
#[macro_use] extern crate nom;
#[macro_use] extern crate log;
#[macro_use] extern crate clap;
#[macro_use] extern crate serde_derive;
extern crate env_logger;
extern crate mio;
extern crate yxorp;
extern crate toml;
extern crate rustc_serialize;
extern crate serde;
extern crate serde_json;
extern crate time;
extern crate libc;

mod config;
mod command;
mod state;

use std::net::{UdpSocket,ToSocketAddrs};
use std::sync::mpsc::{channel};
use std::collections::HashMap;
use std::thread::{self,JoinHandle};
use std::env;
use yxorp::network;
use yxorp::network::metrics::{METRICS,ProxyMetrics};
use log::{LogRecord,LogLevelFilter,LogLevel};
use env_logger::LogBuilder;
use clap::{App,Arg};
use mio::EventLoop;

use command::{Listener,ListenerType};

fn main() {
  let pid = unsafe { libc::getpid() };
  let format = move |record: &LogRecord| {
    match record.level() {
    LogLevel::Debug | LogLevel::Trace => format!("{}\t{}\t{}\t{}\t{}\t|\t{}",
      time::now_utc().rfc3339(), time::precise_time_ns(), pid,
      record.level(), record.args(), record.location().module_path()),
    _ => format!("{}\t{}\t{}\t{}\t{}",
      time::now_utc().rfc3339(), time::precise_time_ns(), pid,
      record.level(), record.args())

    }
  };

  let mut builder = LogBuilder::new();
  builder.format(format).filter(None, LogLevelFilter::Info);

  let matches = App::new("I will not name this thing yxorp")
                        .version(crate_version!())
                        .about("hot reconfigurable proxy")
                        .arg(Arg::with_name("config")
                                    .short("c")
                                    .long("config")
                                    .value_name("FILE")
                                    .help("Sets a custom config file")
                                    .takes_value(true)
                                    .required(true))
                        .get_matches();

  let config_file = matches.value_of("config").unwrap();

  if let Ok(config) = config::Config::load_from_path(config_file) {
    if let Some(log_level) = config.log_level {
     builder.parse(&log_level);
    }

    builder.init().unwrap();
    info!("starting up");

    let metrics_socket = UdpSocket::bind("0.0.0.0:0").unwrap();
    let metrics_host   = (&config.metrics.address[..], config.metrics.port).to_socket_addrs().unwrap().next().unwrap();
    METRICS.lock().unwrap().set_up_remote(metrics_socket, metrics_host);
    let metrics_guard = ProxyMetrics::run();

    let mut listeners = HashMap::new();
    let mut jh_opt: Option<JoinHandle<()>> = None;

    for (ref tag, ref ls) in config.listeners {

      let jg = match ls.listener_type {
        ListenerType::HTTP => {
          //FIXME: make safer
          let conf = ls.to_http().unwrap();
          for _ in 1..ls.worker_count.unwrap_or(1) {
            let (sender, receiver) = channel::<network::ServerMessage>();
            let event_loop = EventLoop::new().unwrap();
            let tx = event_loop.channel();
            let config = conf.clone();
            thread::spawn(move || {
              network::http::start_listener(config, sender, event_loop);
            });
            let l =  Listener::new(tag.clone(), ls.listener_type, ls.address.clone(), tx, receiver);
            listeners.insert(tag.clone(), l);
          }
          let (sender, receiver) = channel::<network::ServerMessage>();
          let event_loop = EventLoop::new().unwrap();
          let tx = event_loop.channel();
          //FIXME: keep this to get a join guard
          let jg = thread::spawn(move || {
            network::http::start_listener(conf, sender, event_loop);
          });
          let l =  Listener::new(tag.clone(), ls.listener_type, ls.address.clone(), tx, receiver);
          listeners.insert(tag.clone(), l);
          jg
        },
        ListenerType::HTTPS => {
          let conf = ls.to_tls().unwrap();
          for _ in 1..ls.worker_count.unwrap_or(1) {
            let (sender, receiver) = channel::<network::ServerMessage>();
            let event_loop = EventLoop::new().unwrap();
            let tx = event_loop.channel();
            let config = conf.clone();
            thread::spawn(move || {
              network::tls::start_listener(config, sender, event_loop);
            });
            let l =  Listener::new(tag.clone(), ls.listener_type, ls.address.clone(), tx, receiver);
            listeners.insert(tag.clone(), l);
          }
          let (sender, receiver) = channel::<network::ServerMessage>();
          let event_loop = EventLoop::new().unwrap();
          let tx = event_loop.channel();
          //FIXME: keep this to get a join guard
          let jg = thread::spawn(move || {
            network::tls::start_listener(conf, sender, event_loop);
          });
          let l =  Listener::new(tag.clone(), ls.listener_type, ls.address.clone(), tx, receiver);
          listeners.insert(tag.clone(), l);
          jg
        },
        _ => unimplemented!()
      };
      jh_opt = Some(jg);
    };

    let buffer_size     = config.command_buffer_size.unwrap_or(10000);
    let max_buffer_size = config.max_command_buffer_size.unwrap_or(buffer_size * 2);
    command::start(config.command_socket, listeners, config.saved_state, buffer_size, max_buffer_size);
    //FIXME: really join on all threads?
    if let Some(jh) = jh_opt {
      let _ = jh.join();
      info!("good bye");
    }
  } else {
    println!("could not load configuration file at '{}', stopping", config_file);
  }
}

<|endoftext|>