<commit_before>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Build a block to mine: gathers transactions from the pool, assembles
//! them into a block and returns it.

use crate::util::RwLock;
use chrono::prelude::{DateTime, NaiveDateTime, Utc};
use rand::{thread_rng, Rng};
use std::sync::Arc;
use std::thread;
use std::time::Duration;

use crate::chain;
use crate::common::types::Error;
use crate::core::core::verifier_cache::VerifierCache;
use crate::core::{consensus, core, global, ser};
use crate::keychain::{ExtKeychain, Identifier, Keychain};
use crate::pool;
use crate::util;
use crate::wallet::{self, BlockFees};

// Ensure a block suitable for mining is built and returned
// If a wallet listener URL is not provided the reward will be "burnt"
// Warning: This call does not return until/unless a new block can be built
pub fn get_block(
	chain: &Arc<chain::Chain>,
	tx_pool: &Arc<RwLock<pool::TransactionPool>>,
	verifier_cache: Arc<RwLock<dyn VerifierCache>>,
	key_id: Option<Identifier>,
	wallet_listener_url: Option<String>,
) -> (core::Block, BlockFees) {
	let wallet_retry_interval = 5;
	// get the latest chain state and build a block on top of it
	let mut result = build_block(
		chain,
		tx_pool,
		verifier_cache.clone(),
		key_id.clone(),
		wallet_listener_url.clone(),
	);
	while let Err(e) = result {
		match e {
			self::Error::Chain(c) => match c.kind() {
				chain::ErrorKind::DuplicateCommitment(_) => {
					debug!(
						"Duplicate commit for potential coinbase detected. Trying next derivation."
					);
				}
				_ => {
					error!("Chain Error: {}", c);
				}
			},
			self::Error::Wallet(_) => {
				error!(
					"Error building new block: Can't connect to wallet listener at {:?}; will retry",
					wallet_listener_url.as_ref().unwrap()
				);
				thread::sleep(Duration::from_secs(wallet_retry_interval));
			}
			ae => {
				warn!("Error building new block: {:?}. Retrying.", ae);
			}
		}
		thread::sleep(Duration::from_millis(100));
		result = build_block(
			chain,
			tx_pool,
			verifier_cache.clone(),
			key_id.clone(),
			wallet_listener_url.clone(),
		);
	}
	return result.unwrap();
}

/// Builds a new block with the chain head as previous and eligible
/// transactions from the pool.
fn build_block(
	chain: &Arc<chain::Chain>,
	tx_pool: &Arc<RwLock<pool::TransactionPool>>,
	verifier_cache: Arc<RwLock<dyn VerifierCache>>,
	key_id: Option<Identifier>,
	wallet_listener_url: Option<String>,
) -> Result<(core::Block, BlockFees), Error> {
	let head = chain.head_header()?;

	// prepare the block header timestamp
	let mut now_sec = Utc::now().timestamp();
	let head_sec = head.timestamp.timestamp();
	if now_sec <= head_sec {
		now_sec = head_sec + 1;
	}

	// Determine the difficulty our block should be at.
	// Note: do not keep the difficulty_iter in scope (it has an active batch).
	let difficulty = consensus::next_difficulty(head.height + 1, chain.difficulty_iter());

	// extract current transaction from the pool
	let txs = tx_pool.read().prepare_mineable_transactions()?;

	// build the coinbase and the block itself
	let fees = txs.iter().map(|tx| tx.fee()).sum();
	let height = head.height + 1;
	let block_fees = BlockFees {
		fees,
		key_id,
		height,
	};

	let (output, kernel, block_fees) = get_coinbase(wallet_listener_url, block_fees)?;
	let mut b = core::Block::from_reward(&head, txs, output, kernel, difficulty.difficulty)?;

	// making sure we're not spending time mining a useless block
	b.validate(&head.total_kernel_offset, verifier_cache)?;

	b.header.pow.nonce = thread_rng().gen();
	b.header.pow.secondary_scaling = difficulty.secondary_scaling;
	b.header.timestamp = DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(now_sec, 0), Utc);

	debug!(
		"Built new block with {} inputs and {} outputs, block difficulty: {}, cumulative difficulty {}",
		b.inputs().len(),
		b.outputs().len(),
		difficulty.difficulty,
		b.header.total_difficulty().to_num(),
	);

	// Now set txhashset roots and sizes on the header of the block being built.
	let roots_result = chain.set_txhashset_roots(&mut b);

	match roots_result {
		Ok(_) => Ok((b, block_fees)),

		// If it's a duplicate commitment, it's likely trying to use
		// a key that's already been derived but not in the wallet
		// for some reason, allow caller to retry
		Err(e) => {
			match e.kind() {
				chain::ErrorKind::DuplicateCommitment(e) => Err(Error::Chain(
					chain::ErrorKind::DuplicateCommitment(e).into(),
				)),

				//Some other issue, possibly duplicate kernel
				_ => {
					error!("Error setting txhashset root to build a block: {:?}", e);
					Err(Error::Chain(
						chain::ErrorKind::Other(format!("{:?}", e)).into(),
					))
				}
			}
		}
	}
}

///
/// Probably only want to do this when testing.
///
fn burn_reward(block_fees: BlockFees) -> Result<(core::Output, core::TxKernel, BlockFees), Error> {
	warn!("Burning block fees: {:?}", block_fees);
	let keychain = ExtKeychain::from_random_seed(global::is_floonet()).unwrap();
	let key_id = ExtKeychain::derive_key_id(1, 1, 0, 0, 0);
	let (out, kernel) =
		crate::core::libtx::reward::output(&keychain, &key_id, block_fees.fees).unwrap();
	Ok((out, kernel, block_fees))
}

// Connect to the wallet listener and get coinbase.
// Warning: If a wallet listener URL is not provided the reward will be "burnt"
fn get_coinbase(
	wallet_listener_url: Option<String>,
	block_fees: BlockFees,
) -> Result<(core::Output, core::TxKernel, BlockFees), Error> {
	match wallet_listener_url {
		None => {
			// Burn it
			return burn_reward(block_fees);
		}
		Some(wallet_listener_url) => {
			let res = wallet::create_coinbase(&wallet_listener_url, &block_fees)?;
			let out_bin = util::from_hex(res.output).unwrap();
			let kern_bin = util::from_hex(res.kernel).unwrap();
			let key_id_bin = util::from_hex(res.key_id).unwrap();
			let output = ser::deserialize(&mut &out_bin[..]).unwrap();
			let kernel = ser::deserialize(&mut &kern_bin[..]).unwrap();
			let key_id = ser::deserialize(&mut &key_id_bin[..]).unwrap();
			let block_fees = BlockFees {
				key_id: Some(key_id),
				..block_fees
			};

			debug!("get_coinbase: {:?}", block_fees);
			return Ok((output, kernel, block_fees));
		}
	}
}
<commit_msg>fallback to empty vec of txs when building block from mineable txs<commit_after>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Build a block to mine: gathers transactions from the pool, assembles
//! them into a block and returns it.

use crate::util::RwLock;
use chrono::prelude::{DateTime, NaiveDateTime, Utc};
use rand::{thread_rng, Rng};
use std::sync::Arc;
use std::thread;
use std::time::Duration;

use crate::chain;
use crate::common::types::Error;
use crate::core::core::verifier_cache::VerifierCache;
use crate::core::{consensus, core, global, ser};
use crate::keychain::{ExtKeychain, Identifier, Keychain};
use crate::pool;
use crate::util;
use crate::wallet::{self, BlockFees};

// Ensure a block suitable for mining is built and returned
// If a wallet listener URL is not provided the reward will be "burnt"
// Warning: This call does not return until/unless a new block can be built
pub fn get_block(
	chain: &Arc<chain::Chain>,
	tx_pool: &Arc<RwLock<pool::TransactionPool>>,
	verifier_cache: Arc<RwLock<dyn VerifierCache>>,
	key_id: Option<Identifier>,
	wallet_listener_url: Option<String>,
) -> (core::Block, BlockFees) {
	let wallet_retry_interval = 5;
	// get the latest chain state and build a block on top of it
	let mut result = build_block(
		chain,
		tx_pool,
		verifier_cache.clone(),
		key_id.clone(),
		wallet_listener_url.clone(),
	);
	while let Err(e) = result {
		match e {
			self::Error::Chain(c) => match c.kind() {
				chain::ErrorKind::DuplicateCommitment(_) => {
					debug!(
						"Duplicate commit for potential coinbase detected. Trying next derivation."
					);
				}
				_ => {
					error!("Chain Error: {}", c);
				}
			},
			self::Error::Wallet(_) => {
				error!(
					"Error building new block: Can't connect to wallet listener at {:?}; will retry",
					wallet_listener_url.as_ref().unwrap()
				);
				thread::sleep(Duration::from_secs(wallet_retry_interval));
			}
			ae => {
				warn!("Error building new block: {:?}. Retrying.", ae);
			}
		}
		thread::sleep(Duration::from_millis(100));
		result = build_block(
			chain,
			tx_pool,
			verifier_cache.clone(),
			key_id.clone(),
			wallet_listener_url.clone(),
		);
	}
	return result.unwrap();
}

/// Builds a new block with the chain head as previous and eligible
/// transactions from the pool.
fn build_block(
	chain: &Arc<chain::Chain>,
	tx_pool: &Arc<RwLock<pool::TransactionPool>>,
	verifier_cache: Arc<RwLock<dyn VerifierCache>>,
	key_id: Option<Identifier>,
	wallet_listener_url: Option<String>,
) -> Result<(core::Block, BlockFees), Error> {
	let head = chain.head_header()?;

	// prepare the block header timestamp
	let mut now_sec = Utc::now().timestamp();
	let head_sec = head.timestamp.timestamp();
	if now_sec <= head_sec {
		now_sec = head_sec + 1;
	}

	// Determine the difficulty our block should be at.
	// Note: do not keep the difficulty_iter in scope (it has an active batch).
	let difficulty = consensus::next_difficulty(head.height + 1, chain.difficulty_iter());

	// Extract current "mineable" transactions from the pool.
	// If this fails for *any* reason then fallback to an empty vec of txs.
	// This will allow us to mine an "empty" block if the txpool is in an
	// invalid (and unexpected) state.
	let txs = tx_pool.read().prepare_mineable_transactions().unwrap_or(vec![]);

	// build the coinbase and the block itself
	let fees = txs.iter().map(|tx| tx.fee()).sum();
	let height = head.height + 1;
	let block_fees = BlockFees {
		fees,
		key_id,
		height,
	};

	let (output, kernel, block_fees) = get_coinbase(wallet_listener_url, block_fees)?;
	let mut b = core::Block::from_reward(&head, txs, output, kernel, difficulty.difficulty)?;

	// making sure we're not spending time mining a useless block
	b.validate(&head.total_kernel_offset, verifier_cache)?;

	b.header.pow.nonce = thread_rng().gen();
	b.header.pow.secondary_scaling = difficulty.secondary_scaling;
	b.header.timestamp = DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(now_sec, 0), Utc);

	debug!(
		"Built new block with {} inputs and {} outputs, block difficulty: {}, cumulative difficulty {}",
		b.inputs().len(),
		b.outputs().len(),
		difficulty.difficulty,
		b.header.total_difficulty().to_num(),
	);

	// Now set txhashset roots and sizes on the header of the block being built.
	match chain.set_txhashset_roots(&mut b) {
		Ok(_) => Ok((b, block_fees)),
		Err(e) => {
			match e.kind() {
				// If this is a duplicate commitment then likely trying to use
				// a key that hass already been derived but not in the wallet
				// for some reason, allow caller to retry.
				chain::ErrorKind::DuplicateCommitment(e) => Err(Error::Chain(
					chain::ErrorKind::DuplicateCommitment(e).into(),
				)),

				// Some other issue, possibly duplicate kernel
				_ => {
					error!("Error setting txhashset root to build a block: {:?}", e);
					Err(Error::Chain(
						chain::ErrorKind::Other(format!("{:?}", e)).into(),
					))
				}
			}
		}
	}
}

///
/// Probably only want to do this when testing.
///
fn burn_reward(block_fees: BlockFees) -> Result<(core::Output, core::TxKernel, BlockFees), Error> {
	warn!("Burning block fees: {:?}", block_fees);
	let keychain = ExtKeychain::from_random_seed(global::is_floonet()).unwrap();
	let key_id = ExtKeychain::derive_key_id(1, 1, 0, 0, 0);
	let (out, kernel) =
		crate::core::libtx::reward::output(&keychain, &key_id, block_fees.fees).unwrap();
	Ok((out, kernel, block_fees))
}

// Connect to the wallet listener and get coinbase.
// Warning: If a wallet listener URL is not provided the reward will be "burnt"
fn get_coinbase(
	wallet_listener_url: Option<String>,
	block_fees: BlockFees,
) -> Result<(core::Output, core::TxKernel, BlockFees), Error> {
	match wallet_listener_url {
		None => {
			// Burn it
			return burn_reward(block_fees);
		}
		Some(wallet_listener_url) => {
			let res = wallet::create_coinbase(&wallet_listener_url, &block_fees)?;
			let out_bin = util::from_hex(res.output).unwrap();
			let kern_bin = util::from_hex(res.kernel).unwrap();
			let key_id_bin = util::from_hex(res.key_id).unwrap();
			let output = ser::deserialize(&mut &out_bin[..]).unwrap();
			let kernel = ser::deserialize(&mut &kern_bin[..]).unwrap();
			let key_id = ser::deserialize(&mut &key_id_bin[..]).unwrap();
			let block_fees = BlockFees {
				key_id: Some(key_id),
				..block_fees
			};

			debug!("get_coinbase: {:?}", block_fees);
			return Ok((output, kernel, block_fees));
		}
	}
}
<|endoftext|>


<commit_before>use IntoBytes;
use frame::*;
use frame::events::ServerEvent;
use types::{CStringList, CString};

/// The structure which represents a body of a frame of type `options`.
pub struct BodyReqRegister {
    pub events: Vec<ServerEvent>
}

impl IntoBytes for BodyReqRegister {
    fn into_cbytes(&self) -> Vec<u8> {
        let events_string_list = CStringList {
            list: self.events
                .iter()
                .map(|event| CString::new(event.as_string()))
                .collect()
        };
        return events_string_list.into_cbytes();
    }
}

// Frame implementation related to BodyReqStartup

// impl Frame {
//     /// Creates new frame of type `options`.
//     pub fn new_req_options() -> Frame {
//         let version = Version::Request;
//         let flag = Flag::Ignore;
//         // sync client
//         let stream: u64 = 0;
//         let opcode = Opcode::Options;
//         let body = BodyReqOptions::new();
//
//         return Frame {
//             version: version,
//             flags: vec![flag],
//             stream: stream,
//             opcode: opcode,
//             body: body.into_cbytes(),
//             // for request frames it's always None
//             tracing_id: None,
//             warnings: vec![]
//         };
//     }
// }
<commit_msg>Create registerframe<commit_after>use IntoBytes;
use frame::*;
use frame::events::ServerEvent;
use types::{CStringList, CString};

/// The structure which represents a body of a frame of type `options`.
pub struct BodyReqRegister {
    pub events: Vec<ServerEvent>
}

impl IntoBytes for BodyReqRegister {
    fn into_cbytes(&self) -> Vec<u8> {
        let events_string_list = CStringList {
            list: self.events
                .iter()
                .map(|event| CString::new(event.as_string()))
                .collect()
        };
        return events_string_list.into_cbytes();
    }
}

// Frame implementation related to BodyReqRegister

impl Frame {
    /// Creates new frame of type `REGISTER`.
    pub fn new_req_register(register: BodyReqRegister) -> Frame {
        let version = Version::Request;
        let flag = Flag::Ignore;
        // sync client
        let stream: u64 = 0;
        let opcode = Opcode::Register;

        return Frame {
            version: version,
            flags: vec![flag],
            stream: stream,
            opcode: opcode,
            body: register.into_cbytes(),
            // for request frames it's always None
            tracing_id: None,
            warnings: vec![]
        };
    }
}
<|endoftext|>


<commit_before>+ *
- I don't really exist.
<commit_msg>Changed<commit_after><|endoftext|>


<commit_before>#![feature(test)]

extern crate base64;
extern crate rand;
extern crate test;

use base64::display;
use base64::{decode, decode_config_buf, decode_config_slice, encode, encode_config_buf,
             encode_config_slice, Base64Encoder, Config, MIME, STANDARD};

use rand::Rng;
use std::io::Write;

use rand::Rng;
use test::Bencher;

#[bench]
fn encode_3b(b: &mut Bencher) {
    do_encode_bench(b, 3)
}

#[bench]
fn encode_3b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3, STANDARD)
}

#[bench]
fn encode_3b_slice(b: &mut Bencher) {
    do_encode_bench_slice(b, 3, STANDARD)
}

#[bench]
fn encode_50b(b: &mut Bencher) {
    do_encode_bench(b, 50)
}

#[bench]
fn encode_50b_display(b: &mut Bencher) {
    do_encode_bench_display(b, 50)
}

#[bench]
fn encode_50b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 50, STANDARD)
}

#[bench]
fn encode_50b_slice(b: &mut Bencher) {
    do_encode_bench_slice(b, 50, STANDARD)
}

#[bench]
fn encode_100b(b: &mut Bencher) {
    do_encode_bench(b, 100)
}

#[bench]
fn encode_100b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 100, STANDARD)
}

#[bench]
fn encode_500b(b: &mut Bencher) {
    do_encode_bench(b, 500)
}

#[bench]
fn encode_500b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 500, STANDARD)
}

#[bench]
fn encode_500b_reuse_buf_mime(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 500, MIME)
}

#[bench]
fn encode_3kib(b: &mut Bencher) {
    do_encode_bench(b, 3 * 1024)
}

#[bench]
fn encode_3kib_display(b: &mut Bencher) {
    do_encode_bench_display(b, 3 * 1024)
}

#[bench]
fn encode_3kib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3 * 1024, STANDARD)
}

#[bench]
fn encode_3kib_slice(b: &mut Bencher) {
    do_encode_bench_slice(b, 3 * 1024, STANDARD)
}

#[bench]
fn encode_3kib_reuse_buf_mime(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3 * 1024, MIME)
}

#[bench]
fn encode_3kib_reuse_buf_stream(b: &mut Bencher) {
    do_encode_bench_stream(b, 3 * 1024, STANDARD)
}

#[bench]
fn encode_3mib(b: &mut Bencher) {
    do_encode_bench(b, 3 * 1024 * 1024)
}

#[bench]
fn encode_3mib_display(b: &mut Bencher) {
    do_encode_bench_display(b, 3 * 1024 * 1024)
}

#[bench]
fn encode_3mib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3 * 1024 * 1024, STANDARD)
}

#[bench]
fn encode_3mib_slice(b: &mut Bencher) {
    do_encode_bench_slice(b, 3 * 1024 * 1024, STANDARD)
}

#[bench]
fn encode_10mib(b: &mut Bencher) {
    do_encode_bench(b, 10 * 1024 * 1024)
}

#[bench]
fn encode_10mib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 10 * 1024 * 1024, STANDARD)
}

#[bench]
fn encode_30mib(b: &mut Bencher) {
    do_encode_bench(b, 30 * 1024 * 1024)
}

#[bench]
fn encode_30mib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 30 * 1024 * 1024, STANDARD)
}

#[bench]
fn encode_30mib_slice(b: &mut Bencher) {
    do_encode_bench_slice(b, 30 * 1024 * 1024, STANDARD)
}

#[bench]
fn decode_3b(b: &mut Bencher) {
    do_decode_bench(b, 3)
}

#[bench]
fn decode_3b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 3)
}

#[bench]
fn decode_3b_slice(b: &mut Bencher) {
    do_decode_bench_slice(b, 3)
}

#[bench]
fn decode_50b(b: &mut Bencher) {
    do_decode_bench(b, 50)
}

#[bench]
fn decode_50b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 50)
}

#[bench]
fn decode_50b_slice(b: &mut Bencher) {
    do_decode_bench_slice(b, 50)
}

#[bench]
fn decode_100b(b: &mut Bencher) {
    do_decode_bench(b, 100)
}

#[bench]
fn decode_100b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 100)
}

#[bench]
fn decode_500b(b: &mut Bencher) {
    do_decode_bench(b, 500)
}

#[bench]
fn decode_500b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 500)
}

#[bench]
fn decode_3kib(b: &mut Bencher) {
    do_decode_bench(b, 3 * 1024)
}

#[bench]
fn decode_3kib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 3 * 1024)
}

#[bench]
fn decode_3kib_slice(b: &mut Bencher) {
    do_decode_bench_slice(b, 3 * 1024)
}

#[bench]
fn decode_3mib(b: &mut Bencher) {
    do_decode_bench(b, 3 * 1024 * 1024)
}

#[bench]
fn decode_3mib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 3 * 1024 * 1024)
}

#[bench]
fn decode_3mib_slice(b: &mut Bencher) {
    do_decode_bench_slice(b, 3 * 1024 * 1024)
}

#[bench]
fn decode_10mib(b: &mut Bencher) {
    do_decode_bench(b, 10 * 1024 * 1024)
}

#[bench]
fn decode_10mib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 10 * 1024 * 1024)
}

#[bench]
fn decode_30mib(b: &mut Bencher) {
    do_decode_bench(b, 30 * 1024 * 1024)
}

#[bench]
fn decode_30mib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 30 * 1024 * 1024)
}

#[bench]
fn decode_30mib_slice(b: &mut Bencher) {
    do_decode_bench_slice(b, 30 * 1024 * 1024)
}

fn do_decode_bench(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size * 3 / 4);
    fill(&mut v);
    let encoded = encode(&v);

    b.bytes = encoded.len() as u64;
    b.iter(|| {
        let orig = decode(&encoded);
        test::black_box(&orig);
    });
}

fn do_decode_bench_reuse_buf(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size * 3 / 4);
    fill(&mut v);
    let encoded = encode(&v);

    let mut buf = Vec::new();
    b.bytes = encoded.len() as u64;
    b.iter(|| {
        decode_config_buf(&encoded, STANDARD, &mut buf).unwrap();
        test::black_box(&buf);
        buf.clear();
    });
}

fn do_decode_bench_slice(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size * 3 / 4);
    fill(&mut v);
    let encoded = encode(&v);

    let mut buf = Vec::new();
    buf.resize(size, 0);
    b.bytes = encoded.len() as u64;
    b.iter(|| {
        decode_config_slice(&encoded, STANDARD, &mut buf).unwrap();
        test::black_box(&buf);
    });
}

fn do_encode_bench(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    b.bytes = v.len() as u64;
    b.iter(|| {
        let e = encode(&v);
        test::black_box(&e);
    });
}

fn do_encode_bench_display(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    b.bytes = v.len() as u64;
    b.iter(|| {
        let e = format!("{}", display::Base64Display::standard(&v));
        test::black_box(&e);
    });
}

fn do_encode_bench_reuse_buf(b: &mut Bencher, size: usize, config: Config) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    let mut buf = String::new();

    b.bytes = v.len() as u64;
    b.iter(|| {
        encode_config_buf(&v, config, &mut buf);
        buf.clear();
    });
}

fn do_encode_bench_slice(b: &mut Bencher, size: usize, config: Config) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    let mut buf = Vec::new();

    b.bytes = v.len() as u64;
    // conservative estimate of encoded size
    buf.resize(size * 2, 0);
    b.iter(|| {
        encode_config_slice(&v, config, &mut buf);
    });
}

fn do_encode_bench_stream(b: &mut Bencher, size: usize, config: Config) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    let mut buf = Vec::new();

    b.bytes = v.len() as u64;

    buf.reserve(size * 2);
    b.iter(|| {
        buf.clear();
        let mut stream_enc = Base64Encoder::new(&mut buf, config);
        stream_enc.write(&v).unwrap();
        stream_enc.flush().unwrap();
    });
}

fn fill(v: &mut Vec<u8>) {
    let cap = v.capacity();
    // weak randomness is plenty; we just want to not be completely friendly to the branch predictor
    let mut r = rand::weak_rng();
    while v.len() < cap {
        v.push(r.gen::<u8>());
    }
}
<commit_msg>Fix merge shrapnel<commit_after>#![feature(test)]

extern crate base64;
extern crate rand;
extern crate test;

use base64::display;
use base64::{decode, decode_config_buf, decode_config_slice, encode, encode_config_buf,
             encode_config_slice, Base64Encoder, Config, MIME, STANDARD};

use rand::Rng;
use std::io::Write;

use test::Bencher;

#[bench]
fn encode_3b(b: &mut Bencher) {
    do_encode_bench(b, 3)
}

#[bench]
fn encode_3b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3, STANDARD)
}

#[bench]
fn encode_3b_slice(b: &mut Bencher) {
    do_encode_bench_slice(b, 3, STANDARD)
}

#[bench]
fn encode_50b(b: &mut Bencher) {
    do_encode_bench(b, 50)
}

#[bench]
fn encode_50b_display(b: &mut Bencher) {
    do_encode_bench_display(b, 50)
}

#[bench]
fn encode_50b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 50, STANDARD)
}

#[bench]
fn encode_50b_slice(b: &mut Bencher) {
    do_encode_bench_slice(b, 50, STANDARD)
}

#[bench]
fn encode_100b(b: &mut Bencher) {
    do_encode_bench(b, 100)
}

#[bench]
fn encode_100b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 100, STANDARD)
}

#[bench]
fn encode_500b(b: &mut Bencher) {
    do_encode_bench(b, 500)
}

#[bench]
fn encode_500b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 500, STANDARD)
}

#[bench]
fn encode_500b_reuse_buf_mime(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 500, MIME)
}

#[bench]
fn encode_3kib(b: &mut Bencher) {
    do_encode_bench(b, 3 * 1024)
}

#[bench]
fn encode_3kib_display(b: &mut Bencher) {
    do_encode_bench_display(b, 3 * 1024)
}

#[bench]
fn encode_3kib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3 * 1024, STANDARD)
}

#[bench]
fn encode_3kib_slice(b: &mut Bencher) {
    do_encode_bench_slice(b, 3 * 1024, STANDARD)
}

#[bench]
fn encode_3kib_reuse_buf_mime(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3 * 1024, MIME)
}

#[bench]
fn encode_3kib_reuse_buf_stream(b: &mut Bencher) {
    do_encode_bench_stream(b, 3 * 1024, STANDARD)
}

#[bench]
fn encode_3mib(b: &mut Bencher) {
    do_encode_bench(b, 3 * 1024 * 1024)
}

#[bench]
fn encode_3mib_display(b: &mut Bencher) {
    do_encode_bench_display(b, 3 * 1024 * 1024)
}

#[bench]
fn encode_3mib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3 * 1024 * 1024, STANDARD)
}

#[bench]
fn encode_3mib_slice(b: &mut Bencher) {
    do_encode_bench_slice(b, 3 * 1024 * 1024, STANDARD)
}

#[bench]
fn encode_10mib(b: &mut Bencher) {
    do_encode_bench(b, 10 * 1024 * 1024)
}

#[bench]
fn encode_10mib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 10 * 1024 * 1024, STANDARD)
}

#[bench]
fn encode_30mib(b: &mut Bencher) {
    do_encode_bench(b, 30 * 1024 * 1024)
}

#[bench]
fn encode_30mib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 30 * 1024 * 1024, STANDARD)
}

#[bench]
fn encode_30mib_slice(b: &mut Bencher) {
    do_encode_bench_slice(b, 30 * 1024 * 1024, STANDARD)
}

#[bench]
fn decode_3b(b: &mut Bencher) {
    do_decode_bench(b, 3)
}

#[bench]
fn decode_3b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 3)
}

#[bench]
fn decode_3b_slice(b: &mut Bencher) {
    do_decode_bench_slice(b, 3)
}

#[bench]
fn decode_50b(b: &mut Bencher) {
    do_decode_bench(b, 50)
}

#[bench]
fn decode_50b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 50)
}

#[bench]
fn decode_50b_slice(b: &mut Bencher) {
    do_decode_bench_slice(b, 50)
}

#[bench]
fn decode_100b(b: &mut Bencher) {
    do_decode_bench(b, 100)
}

#[bench]
fn decode_100b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 100)
}

#[bench]
fn decode_500b(b: &mut Bencher) {
    do_decode_bench(b, 500)
}

#[bench]
fn decode_500b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 500)
}

#[bench]
fn decode_3kib(b: &mut Bencher) {
    do_decode_bench(b, 3 * 1024)
}

#[bench]
fn decode_3kib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 3 * 1024)
}

#[bench]
fn decode_3kib_slice(b: &mut Bencher) {
    do_decode_bench_slice(b, 3 * 1024)
}

#[bench]
fn decode_3mib(b: &mut Bencher) {
    do_decode_bench(b, 3 * 1024 * 1024)
}

#[bench]
fn decode_3mib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 3 * 1024 * 1024)
}

#[bench]
fn decode_3mib_slice(b: &mut Bencher) {
    do_decode_bench_slice(b, 3 * 1024 * 1024)
}

#[bench]
fn decode_10mib(b: &mut Bencher) {
    do_decode_bench(b, 10 * 1024 * 1024)
}

#[bench]
fn decode_10mib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 10 * 1024 * 1024)
}

#[bench]
fn decode_30mib(b: &mut Bencher) {
    do_decode_bench(b, 30 * 1024 * 1024)
}

#[bench]
fn decode_30mib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 30 * 1024 * 1024)
}

#[bench]
fn decode_30mib_slice(b: &mut Bencher) {
    do_decode_bench_slice(b, 30 * 1024 * 1024)
}

fn do_decode_bench(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size * 3 / 4);
    fill(&mut v);
    let encoded = encode(&v);

    b.bytes = encoded.len() as u64;
    b.iter(|| {
        let orig = decode(&encoded);
        test::black_box(&orig);
    });
}

fn do_decode_bench_reuse_buf(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size * 3 / 4);
    fill(&mut v);
    let encoded = encode(&v);

    let mut buf = Vec::new();
    b.bytes = encoded.len() as u64;
    b.iter(|| {
        decode_config_buf(&encoded, STANDARD, &mut buf).unwrap();
        test::black_box(&buf);
        buf.clear();
    });
}

fn do_decode_bench_slice(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size * 3 / 4);
    fill(&mut v);
    let encoded = encode(&v);

    let mut buf = Vec::new();
    buf.resize(size, 0);
    b.bytes = encoded.len() as u64;
    b.iter(|| {
        decode_config_slice(&encoded, STANDARD, &mut buf).unwrap();
        test::black_box(&buf);
    });
}

fn do_encode_bench(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    b.bytes = v.len() as u64;
    b.iter(|| {
        let e = encode(&v);
        test::black_box(&e);
    });
}

fn do_encode_bench_display(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    b.bytes = v.len() as u64;
    b.iter(|| {
        let e = format!("{}", display::Base64Display::standard(&v));
        test::black_box(&e);
    });
}

fn do_encode_bench_reuse_buf(b: &mut Bencher, size: usize, config: Config) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    let mut buf = String::new();

    b.bytes = v.len() as u64;
    b.iter(|| {
        encode_config_buf(&v, config, &mut buf);
        buf.clear();
    });
}

fn do_encode_bench_slice(b: &mut Bencher, size: usize, config: Config) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    let mut buf = Vec::new();

    b.bytes = v.len() as u64;
    // conservative estimate of encoded size
    buf.resize(size * 2, 0);
    b.iter(|| {
        encode_config_slice(&v, config, &mut buf);
    });
}

fn do_encode_bench_stream(b: &mut Bencher, size: usize, config: Config) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    let mut buf = Vec::new();

    b.bytes = v.len() as u64;

    buf.reserve(size * 2);
    b.iter(|| {
        buf.clear();
        let mut stream_enc = Base64Encoder::new(&mut buf, config);
        stream_enc.write(&v).unwrap();
        stream_enc.flush().unwrap();
    });
}

fn fill(v: &mut Vec<u8>) {
    let cap = v.capacity();
    // weak randomness is plenty; we just want to not be completely friendly to the branch predictor
    let mut r = rand::weak_rng();
    while v.len() < cap {
        v.push(r.gen::<u8>());
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

fn main() {
    // bad arguments to the format! call

    format!("{}");            //~ ERROR: invalid reference to argument

    format!("{1}", 1);        //~ ERROR: invalid reference to argument `1`
                            //~^ ERROR: argument never used
    format!("{foo}");         //~ ERROR: no argument named `foo`

    format!("", 1, 2);                 //~ ERROR: multiple unused formatting arguments
    format!("{}", 1, 2);               //~ ERROR: argument never used
    format!("{1}", 1, 2);              //~ ERROR: argument never used
    format!("{}", 1, foo=2);           //~ ERROR: named argument never used
    format!("{foo}", 1, foo=2);        //~ ERROR: argument never used
    format!("", foo=2);                //~ ERROR: named argument never used

    format!("{foo}", foo=1, foo=2);    //~ ERROR: duplicate argument
    format!("", foo=1, 2);             //~ ERROR: positional arguments cannot follow

    // bad number of arguments, see #15780

    format!("{0}");
    //~^ ERROR invalid reference to argument `0` (no arguments given)

    format!("{0} {1}", 1);
    //~^ ERROR invalid reference to argument `1` (there is 1 argument)

    format!("{0} {1} {2}", 1, 2);
    //~^ ERROR invalid reference to argument `2` (there are 2 arguments)

    format!("{0} {1}");
    //~^ ERROR invalid reference to argument `0` (no arguments given)
    //~^^ ERROR invalid reference to argument `1` (no arguments given)

    // bad named arguments, #35082

    format!("{valuea} {valueb}", valuea=5, valuec=7);
    //~^ ERROR there is no argument named `valueb`
    //~^^ ERROR named argument never used

    // bad syntax of the format string

    format!("{"); //~ ERROR: expected `'}'` but string was terminated

    format!("foo } bar"); //~ ERROR: unmatched `}` found
    format!("foo }"); //~ ERROR: unmatched `}` found

    format!("foo %s baz", "bar"); //~ ERROR: argument never used
}
<commit_msg>Add tests for new format! error message<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

fn main() {
    // bad arguments to the format! call

    // bad number of arguments, see #44954 (originally #15780)

    format!("{}");
    //~^ ERROR: 1 positional argument in format string, but no arguments were given

    format!("{1}", 1);
    //~^ ERROR: 1 positional argument in format string, but there is only 1 argument
    //~^^ ERROR: argument never used

    format!("{} {}");
    //~^ ERROR: 2 positional arguments in format string, but no arguments were given

    format!("{0} {1}", 1);
    //~^ ERROR: 2 positional arguments in format string, but there is only 1 argument

    format!("{0} {1} {2}", 1, 2);
    //~^ ERROR: 3 positional arguments in format string, but there are only 2 arguments

    format!("{} {value} {} {}", 1, value=2);
    //~^ ERROR: invalid reference to positional argument 2 (there are only 2 arguments)
    format!("{name} {value} {} {} {} {} {} {}", 0, name=1, value=2);
    //~^ ERROR: invalid reference to positional arguments 3, 4 and 5 (there are only 3 arguments)

    format!("{foo}");                //~ ERROR: no argument named `foo`
    format!("", 1, 2);               //~ ERROR: multiple unused formatting arguments
    format!("{}", 1, 2);             //~ ERROR: argument never used
    format!("{1}", 1, 2);            //~ ERROR: argument never used
    format!("{}", 1, foo=2);         //~ ERROR: named argument never used
    format!("{foo}", 1, foo=2);      //~ ERROR: argument never used
    format!("", foo=2);              //~ ERROR: named argument never used

    format!("{foo}", foo=1, foo=2);  //~ ERROR: duplicate argument
    format!("", foo=1, 2);           //~ ERROR: positional arguments cannot follow

    // bad named arguments, #35082

    format!("{valuea} {valueb}", valuea=5, valuec=7);
    //~^ ERROR there is no argument named `valueb`
    //~^^ ERROR named argument never used

    // bad syntax of the format string

    format!("{"); //~ ERROR: expected `'}'` but string was terminated

    format!("foo } bar"); //~ ERROR: unmatched `}` found
    format!("foo }"); //~ ERROR: unmatched `}` found

    format!("foo %s baz", "bar"); //~ ERROR: argument never used
}
<|endoftext|>


<commit_before>// Edge Operation Genome

use evo::prob::{Probability, ProbabilityValue};
use evo::crossover::linear_2point_crossover_random;
use rand::Rng;
use rand::distributions::{IndependentSample, Weighted, WeightedChoice};
use petgraph::{Directed, Graph};
use petgraph::graph::NodeIndex;
use graph_edge_evolution::{EdgeOperation, GraphBuilder};

#[derive(Clone, Debug)]
pub struct EdgeOpsGenome {
    edge_ops: Vec<EdgeOperation<f32, ()>>,
}

#[derive(Clone)]
enum Op {
    Dup,
    Split,
    Loop,
    Merge,
    Next,
    Parent,
    Reverse,
}

fn generate_random_edge_operation<R: Rng>(rng: &mut R) -> EdgeOperation<f32, ()> {
    let mut items = [Weighted {
                         weight: 1,
                         item: Op::Dup,
                     },
                     Weighted {
                         weight: 3,
                         item: Op::Split,
                     },
                     Weighted {
                         weight: 1,
                         item: Op::Loop,
                     },
                     Weighted {
                         weight: 1,
                         item: Op::Merge,
                     },
                     Weighted {
                         weight: 2,
                         item: Op::Next,
                     },
                     Weighted {
                         weight: 2,
                         item: Op::Parent,
                     },
                     Weighted {
                         weight: 2,
                         item: Op::Reverse,
                     }];
    let wc = WeightedChoice::new(&mut items);
    match wc.ind_sample(rng) {
        Op::Dup => {
            EdgeOperation::Duplicate { weight: 0.0 }
        }
        Op::Split => {
            EdgeOperation::Split { weight: 0.0 }
        }
        Op::Loop => {
            EdgeOperation::Loop { weight: 0.0 }
        }
        Op::Merge => {
            EdgeOperation::Merge { n: rng.gen::<u32>() }
        }
        Op::Next => {
            EdgeOperation::Next { n: rng.gen::<u32>() }
        }
        Op::Parent => {
            EdgeOperation::Parent { n: rng.gen::<u32>() }
        }
        Op::Reverse => {
            EdgeOperation::Reverse
        }
    }
}

impl EdgeOpsGenome {
    pub fn random<R: Rng>(rng: &mut R, len: usize) -> EdgeOpsGenome {
        let edge_ops: Vec<_> = (0..len)
                                   .map(|_| generate_random_edge_operation(rng))
                                   .collect();

        EdgeOpsGenome { edge_ops: edge_ops }
    }

    pub fn len(&self) -> usize {
        self.edge_ops.len()
    }

    pub fn mate<R: Rng>(rng: &mut R, p1: &EdgeOpsGenome, p2: &EdgeOpsGenome) -> EdgeOpsGenome {
        EdgeOpsGenome {
            edge_ops: linear_2point_crossover_random(rng, &p1.edge_ops[..], &p2.edge_ops[..]),
        }
    }

    pub fn mutate<R: Rng>(&mut self, rng: &mut R, mutate_elem_prob: Probability) {
        for edge_op in self.edge_ops.iter_mut() {
            if rng.gen::<ProbabilityValue>().is_probable_with(mutate_elem_prob) {
                let new_edge_op = match edge_op {
                    &mut EdgeOperation::Merge{..} => {
                        EdgeOperation::Merge { n: rng.gen::<u32>() }
                    }
                    &mut EdgeOperation::Next{..} => {
                        EdgeOperation::Next { n: rng.gen::<u32>() }
                    }
                    &mut EdgeOperation::Parent{..} => {
                        EdgeOperation::Parent { n: rng.gen::<u32>() }
                    }
                    ref op => {
                        (*op).clone()
                    }
                };

                *edge_op = new_edge_op;
            }
        }
    }

    pub fn to_graph(&self) -> Graph<(), (), Directed, u32> {
        let mut builder = GraphBuilder::new();
        for op in self.edge_ops.iter() {
            builder.apply_operation(op.clone());
        }
        let edge_list = builder.to_edge_list();

        let mut g: Graph<(), (), Directed, u32> = Graph::new();
        let n = edge_list.len();
        for _ in 0..n {
            let _ = g.add_node(());
        }

        for (i, node) in edge_list.iter().enumerate() {
            for &(j, _weight) in node.iter() {
                g.add_edge(NodeIndex::new(i), NodeIndex::new(j), ());
            }
        }

        return g;
    }
}
<commit_msg>Weight all operations the same<commit_after>// Edge Operation Genome

use evo::prob::{Probability, ProbabilityValue};
use evo::crossover::linear_2point_crossover_random;
use rand::Rng;
use rand::distributions::{IndependentSample, Weighted, WeightedChoice};
use petgraph::{Directed, Graph};
use petgraph::graph::NodeIndex;
use graph_edge_evolution::{EdgeOperation, GraphBuilder};

#[derive(Clone, Debug)]
pub struct EdgeOpsGenome {
    edge_ops: Vec<EdgeOperation<f32, ()>>,
}

#[derive(Clone)]
enum Op {
    Dup,
    Split,
    Loop,
    Merge,
    Next,
    Parent,
    Reverse,
}

fn generate_random_edge_operation<R: Rng>(rng: &mut R) -> EdgeOperation<f32, ()> {
    let mut items = [Weighted {
                         weight: 1,
                         item: Op::Dup,
                     },
                     Weighted {
                         weight: 1,
                         item: Op::Split,
                     },
                     Weighted {
                         weight: 1,
                         item: Op::Loop,
                     },
                     Weighted {
                         weight: 1,
                         item: Op::Merge,
                     },
                     Weighted {
                         weight: 1,
                         item: Op::Next,
                     },
                     Weighted {
                         weight: 1,
                         item: Op::Parent,
                     },
                     Weighted {
                         weight: 1,
                         item: Op::Reverse,
                     }];
    let wc = WeightedChoice::new(&mut items);
    match wc.ind_sample(rng) {
        Op::Dup => {
            EdgeOperation::Duplicate { weight: 0.0 }
        }
        Op::Split => {
            EdgeOperation::Split { weight: 0.0 }
        }
        Op::Loop => {
            EdgeOperation::Loop { weight: 0.0 }
        }
        Op::Merge => {
            EdgeOperation::Merge { n: rng.gen::<u32>() }
        }
        Op::Next => {
            EdgeOperation::Next { n: rng.gen::<u32>() }
        }
        Op::Parent => {
            EdgeOperation::Parent { n: rng.gen::<u32>() }
        }
        Op::Reverse => {
            EdgeOperation::Reverse
        }
    }
}

impl EdgeOpsGenome {
    pub fn random<R: Rng>(rng: &mut R, len: usize) -> EdgeOpsGenome {
        let edge_ops: Vec<_> = (0..len)
                                   .map(|_| generate_random_edge_operation(rng))
                                   .collect();

        EdgeOpsGenome { edge_ops: edge_ops }
    }

    pub fn len(&self) -> usize {
        self.edge_ops.len()
    }

    pub fn mate<R: Rng>(rng: &mut R, p1: &EdgeOpsGenome, p2: &EdgeOpsGenome) -> EdgeOpsGenome {
        EdgeOpsGenome {
            edge_ops: linear_2point_crossover_random(rng, &p1.edge_ops[..], &p2.edge_ops[..]),
        }
    }

    pub fn mutate<R: Rng>(&mut self, rng: &mut R, mutate_elem_prob: Probability) {
        for edge_op in self.edge_ops.iter_mut() {
            if rng.gen::<ProbabilityValue>().is_probable_with(mutate_elem_prob) {
                let new_edge_op = match edge_op {
                    &mut EdgeOperation::Merge{..} => {
                        EdgeOperation::Merge { n: rng.gen::<u32>() }
                    }
                    &mut EdgeOperation::Next{..} => {
                        EdgeOperation::Next { n: rng.gen::<u32>() }
                    }
                    &mut EdgeOperation::Parent{..} => {
                        EdgeOperation::Parent { n: rng.gen::<u32>() }
                    }
                    ref op => {
                        (*op).clone()
                    }
                };

                *edge_op = new_edge_op;
            }
        }
    }

    pub fn to_graph(&self) -> Graph<(), (), Directed, u32> {
        let mut builder = GraphBuilder::new();
        for op in self.edge_ops.iter() {
            builder.apply_operation(op.clone());
        }
        let edge_list = builder.to_edge_list();

        let mut g: Graph<(), (), Directed, u32> = Graph::new();
        let n = edge_list.len();
        for _ in 0..n {
            let _ = g.add_node(());
        }

        for (i, node) in edge_list.iter().enumerate() {
            for &(j, _weight) in node.iter() {
                g.add_edge(NodeIndex::new(i), NodeIndex::new(j), ());
            }
        }

        return g;
    }
}
<|endoftext|>


<commit_before>#![allow(unused_variables, dead_code)]
#[macro_use]
extern crate r2pipe;
extern crate docopt;
extern crate rustc_serialize;
extern crate radeco_lib;
//extern crate core;

mod radeco;
mod structs;

use rustc_serialize::json;
use docopt::Docopt;
use std::process::exit;
use std::fs::{File};
use std::io::{Write, Read};

const VERSION: &'static str = env!("CARGO_PKG_VERSION");

#[derive(Debug, RustcDecodable)]
struct Args {
    flag_output: String,
    flag_version: bool,
    flag_shell: bool,
    arg_file: Option<String>,
	flag_from_json: bool,
	flag_json_builder: bool,
	cmd_run: bool,
}

static USAGE: &'static str = "
radeco. The radare2 decompiler.

Usage:
  radeco <file>
  radeco [--json-builder]
  radeco run [options] [<file>]
  radeco --shell <file>
  radeco --output=<output> <file>
  radeco --version

Options:
  -h --help              Show this screen.
  --version              Show version.
  --shell                Run interactive prompt.
  --output=<mode>        Select output mode.
  --from-json            Run radeco based on config and information
				         from input json file. Needs an input file.
  --json-builder         Interactive shell used to build the config
				         json for radeco. When used with run, the
				         config generated is automatically used to
						 run radeco rather than dumping it to a file.
";

//fn radeco_file(args:&Args) -> i32 {
    //let mut r = Radeco::file("/bin/ls".to_owned()).unwrap();
    //if args.flag_shell {
        //r.shell();
    //} else {
        //println!("Batch stuff here");
    //}
    //r.close();
    //0
//}

//fn radeco_pipe(args:&Args) -> i32 {
    //let mut r = Radeco::pipe().unwrap();
    //if args.flag_shell {
        //r.shell();
    //} else {
        //println!("Running radeco via pipe");
		//// TODO get offset, function, bin info, ..
    //}
    //r.close();
    //0
//}

fn write_file(fname: String, res: String) {
	let mut file = File::create(fname).unwrap();
	file.write_all(res.as_bytes()).unwrap();
}

fn json_builder(run: bool) {
	let inp = structs::input_builder();
	let mut runner = inp.validate().unwrap();
	if !run {
		let mut name = inp.name.clone().unwrap();
		let json = json::as_pretty_json(&inp);
		let raw_json = format!("{}", json);
		name.push_str(".json");
		write_file(name, raw_json);
	} else {
		runner.run();
	}
}

fn read_json(fname: String) -> structs::Input {
	let mut raw_json = String::new();
	let _ = File::open(fname).unwrap().read_to_string(&mut raw_json);
	json::decode(&*raw_json).unwrap()
}

fn main() {
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());
    if args.flag_version {
        println!("Version: {:?}", VERSION);
        exit(0);
    }
    //if args.arg_file != "" {
        //if args.arg_file == "-" {
            //exit(radeco_pipe(&args));
        //} else {
            //exit(radeco_file(&args));
        //}
    //}

	if args.flag_json_builder {
		json_builder(args.cmd_run);
	}

	if args.flag_from_json {
		if args.arg_file.is_none() {
			println!("{}", USAGE);
		}

		let inp = read_json(args.arg_file.unwrap());
		let mut runner = inp.validate().unwrap();
		runner.run();
	}
}
<commit_msg>Adds dump() to emit output<commit_after>#![allow(unused_variables, dead_code)]
#[macro_use]
extern crate r2pipe;
extern crate docopt;
extern crate rustc_serialize;
extern crate radeco_lib;
//extern crate core;

mod radeco;
mod structs;

use rustc_serialize::json;
use docopt::Docopt;
use std::process::exit;
use std::fs::{File};
use std::io::{Write, Read};

const VERSION: &'static str = env!("CARGO_PKG_VERSION");

#[derive(Debug, RustcDecodable)]
struct Args {
    flag_output: String,
    flag_version: bool,
    flag_shell: bool,
    arg_file: Option<String>,
	flag_from_json: bool,
	flag_json_builder: bool,
	cmd_run: bool,
}

static USAGE: &'static str = "
radeco. The radare2 decompiler.

Usage:
  radeco <file>
  radeco [--json-builder]
  radeco run [options] [<file>]
  radeco --shell <file>
  radeco --output=<output> <file>
  radeco --version

Options:
  -h --help              Show this screen.
  --version              Show version.
  --shell                Run interactive prompt.
  --output=<mode>        Select output mode.
  --from-json            Run radeco based on config and information
				         from input json file. Needs an input file.
  --json-builder         Interactive shell used to build the config
				         json for radeco. When used with run, the
				         config generated is automatically used to
						 run radeco rather than dumping it to a file.
";

//fn radeco_file(args:&Args) -> i32 {
    //let mut r = Radeco::file("/bin/ls".to_owned()).unwrap();
    //if args.flag_shell {
        //r.shell();
    //} else {
        //println!("Batch stuff here");
    //}
    //r.close();
    //0
//}

//fn radeco_pipe(args:&Args) -> i32 {
    //let mut r = Radeco::pipe().unwrap();
    //if args.flag_shell {
        //r.shell();
    //} else {
        //println!("Running radeco via pipe");
		//// TODO get offset, function, bin info, ..
    //}
    //r.close();
    //0
//}

fn write_file(fname: String, res: String) {
	let mut file = File::create(fname).unwrap();
	file.write_all(res.as_bytes()).unwrap();
}

fn json_builder(run: bool) {
	let inp = structs::input_builder();
	let mut runner = inp.validate().unwrap();
	if !run {
		let mut name = inp.name.clone().unwrap();
		let json = json::as_pretty_json(&inp);
		let raw_json = format!("{}", json);
		name.push_str(".json");
		write_file(name, raw_json);
	} else {
		runner.run();
		runner.dump();
	}
}

fn read_json(fname: String) -> structs::Input {
	let mut raw_json = String::new();
	let _ = File::open(fname).unwrap().read_to_string(&mut raw_json);
	json::decode(&*raw_json).unwrap()
}

fn main() {
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());
    if args.flag_version {
        println!("Version: {:?}", VERSION);
        exit(0);
    }
    //if args.arg_file != "" {
        //if args.arg_file == "-" {
            //exit(radeco_pipe(&args));
        //} else {
            //exit(radeco_file(&args));
        //}
    //}

	if args.flag_json_builder {
		json_builder(args.cmd_run);
	}

	if args.flag_from_json {
		if args.arg_file.is_none() {
			println!("{}", USAGE);
		}

		let inp = read_json(args.arg_file.unwrap());
		let mut runner = inp.validate().unwrap();
		runner.run();
		runner.dump();
	}
}
<|endoftext|>


<commit_before>use std::convert::TryInto;

use proc_macro2::Span;
use quote::quote;

use syn::{Data, DeriveInput, Field, Ident, Lit, Path, Visibility};
use syn::{Meta, MetaList, MetaNameValue, NestedMeta};

/// Representing the struct we are deriving
pub struct Input {
    /// The input struct name
    pub name: Ident,
    /// The list of fields in the struct
    pub fields: Vec<Field>,
    /// The struct overall visibility
    pub visibility: Visibility,
    /// Additional attributes requested with `#[soa_attr(...)]` or
    /// `#[soa_derive()]`
    pub attrs: ExtraAttributes,
}

pub struct ExtraAttributes {
    // did the user explicitly asked us to derive clone?
    pub derive_clone: bool,

    pub vec: Vec<Meta>,
    pub slice: Vec<Meta>,
    pub slice_mut: Vec<Meta>,
    pub ref_: Vec<Meta>,
    pub ref_mut: Vec<Meta>,
    pub ptr: Vec<Meta>,
    pub ptr_mut: Vec<Meta>,
}

impl ExtraAttributes {
    fn new() -> ExtraAttributes {
        ExtraAttributes {
            derive_clone: false,
            vec: Vec::new(),
            slice: Vec::new(),
            slice_mut: Vec::new(),
            ref_: Vec::new(),
            ref_mut: Vec::new(),
            ptr: Vec::new(),
            ptr_mut: Vec::new(),
        }
    }

    /// parse a single `#[soa_attr(...)]`
    fn parse(&mut self, meta: &Meta) {
        match meta {
            Meta::List(MetaList { nested, .. }) => {
                let [soa_type, attr]: [NestedMeta; 2] = nested.into_iter()
                    .cloned()
                    .collect::<Vec<_>>()
                    .try_into()
                    .unwrap_or_else(|_| panic!(
                        "expected #[soa_attr(\"Types, To, Add, Attribute\", \
                        \"Attribute\")], got #[{}]", quote!(#meta)
                    ));

                let attr = match attr {
                    NestedMeta::Meta(meta) => meta,
                    NestedMeta::Lit(_) => {
                        panic!("expected an attribute, got {}", quote!(attr))
                    }
                };

                match soa_type {
                    NestedMeta::Meta(Meta::Path(path)) => match path.get_ident() {
                        Some(ident) => match ident.to_string().as_str() {
                            "Vec" => {
                                self.vec.push(attr);
                            },
                            "Slice" => {
                                self.slice.push(attr);
                            },
                            "SliceMut" => {
                                self.slice_mut.push(attr);
                            },
                            "Ref" => {
                                self.ref_.push(attr);
                            },
                            "RefMut" => {
                                self.ref_mut.push(attr);
                            },
                            "Ptr" => {
                                self.ptr.push(attr);
                            },
                            "PtrMut" => {
                                self.ptr_mut.push(attr);
                            },
                            _ => panic!("expected a soa type, got {}", ident),
                        },
                        None => {
                            panic!("expected a soa type, got {}", quote!(#path));
                        }
                    },
                    _ => {
                        panic!("expected a soa type, got {}", quote!(#soa_type));
                    }
                };
            }
            _ => panic!("expected #[soa_attr(...)], got #[{}]", quote!(#meta)),
        }
    }

    /// Add a single trait from `#[soa_derive]`
    fn add_derive(&mut self, trait_: &str) {
        static EXCEPTIONS: &[&str] = &["Clone", "Deserialize", "Serialize"];

        let derive = create_derive_meta(trait_);
        if !EXCEPTIONS.contains(&trait_) {
            self.slice.push(derive.clone());
            self.slice_mut.push(derive.clone());
            self.ref_.push(derive.clone());
            self.ref_mut.push(derive.clone());
            self.ptr.push(derive.clone());
            self.ptr_mut.push(derive.clone());
        }

        // always add this derive to the Vec struct
        self.vec.push(derive);

        if trait_ == "Clone" {
            self.derive_clone = true;
        }
    }
}

fn create_derive_meta(name: &str) -> Meta {
    let mut nested = syn::punctuated::Punctuated::new();
    nested.push(NestedMeta::Meta(Meta::Path(Path::from(
        Ident::new(name, Span::call_site())
    ))));

    Meta::List(MetaList {
        path: Path::from(Ident::new("derive", Span::call_site())),
        paren_token: syn::token::Paren {span: Span::call_site()},
        nested: nested
    })
}

impl Input {
    pub fn new(input: DeriveInput) -> Input {
        let fields = match input.data {
            Data::Struct(s) => s.fields.iter().cloned().collect::<Vec<_>>(),
            _ => panic!("#[derive(StructOfArray)] only supports struct"),
        };

        if fields.is_empty() {
            panic!("#[derive(StructOfArray)] only supports struct with fields");
        }

        let mut extra_attrs = ExtraAttributes::new();

        for attr in input.attrs {
            if let Ok(meta) = attr.parse_meta() {
                if meta.path().is_ident("soa_derive") {
                    match meta {
                        Meta::NameValue(MetaNameValue {
                            lit: Lit::Str(string),
                            ..
                        }) => {
                            for value in string.value().split(',') {
                                extra_attrs.add_derive(value.trim());
                            }
                        }
                        _ => panic!(
                            "expected #[soa_derive = \"Traits, To, Derive\"], got #[{}]",
                            quote!(#meta)
                        ),
                    }
                } else if meta.path().is_ident("soa_attr") {
                    extra_attrs.parse(&meta);
                }
            }
        }

        Input {
            name: input.ident,
            fields: fields,
            visibility: input.vis,
            attrs: extra_attrs,
        }
    }

    pub fn vec_name(&self) -> Ident {
        Ident::new(&format!("{}Vec", self.name), Span::call_site())
    }

    pub fn slice_name(&self) -> Ident {
        Ident::new(&format!("{}Slice", self.name), Span::call_site())
    }

    pub fn slice_mut_name(&self) -> Ident {
        Ident::new(&format!("{}SliceMut", self.name), Span::call_site())
    }

    pub fn ref_name(&self) -> Ident {
        Ident::new(&format!("{}Ref", self.name), Span::call_site())
    }

    pub fn ref_mut_name(&self) -> Ident {
        Ident::new(&format!("{}RefMut", self.name), Span::call_site())
    }

    pub fn ptr_name(&self) -> Ident {
        Ident::new(&format!("{}Ptr", self.name), Span::call_site())
    }

    pub fn ptr_mut_name(&self) -> Ident {
        Ident::new(&format!("{}PtrMut", self.name), Span::call_site())
    }
}
<commit_msg>Improve error message when trying to soa_derive Copy<commit_after>use std::convert::TryInto;

use proc_macro2::Span;
use quote::quote;

use syn::{Data, DeriveInput, Field, Ident, Lit, Path, Visibility};
use syn::{Meta, MetaList, MetaNameValue, NestedMeta};

/// Representing the struct we are deriving
pub struct Input {
    /// The input struct name
    pub name: Ident,
    /// The list of fields in the struct
    pub fields: Vec<Field>,
    /// The struct overall visibility
    pub visibility: Visibility,
    /// Additional attributes requested with `#[soa_attr(...)]` or
    /// `#[soa_derive()]`
    pub attrs: ExtraAttributes,
}

pub struct ExtraAttributes {
    // did the user explicitly asked us to derive clone?
    pub derive_clone: bool,

    pub vec: Vec<Meta>,
    pub slice: Vec<Meta>,
    pub slice_mut: Vec<Meta>,
    pub ref_: Vec<Meta>,
    pub ref_mut: Vec<Meta>,
    pub ptr: Vec<Meta>,
    pub ptr_mut: Vec<Meta>,
}

impl ExtraAttributes {
    fn new() -> ExtraAttributes {
        ExtraAttributes {
            derive_clone: false,
            vec: Vec::new(),
            slice: Vec::new(),
            slice_mut: Vec::new(),
            ref_: Vec::new(),
            ref_mut: Vec::new(),
            ptr: Vec::new(),
            ptr_mut: Vec::new(),
        }
    }

    /// parse a single `#[soa_attr(...)]`
    fn parse(&mut self, meta: &Meta) {
        match meta {
            Meta::List(MetaList { nested, .. }) => {
                let [soa_type, attr]: [NestedMeta; 2] = nested.into_iter()
                    .cloned()
                    .collect::<Vec<_>>()
                    .try_into()
                    .unwrap_or_else(|_| panic!(
                        "expected #[soa_attr(\"Types, To, Add, Attribute\", \
                        \"Attribute\")], got #[{}]", quote!(#meta)
                    ));

                let attr = match attr {
                    NestedMeta::Meta(meta) => meta,
                    NestedMeta::Lit(_) => {
                        panic!("expected an attribute, got {}", quote!(attr))
                    }
                };

                match soa_type {
                    NestedMeta::Meta(Meta::Path(path)) => match path.get_ident() {
                        Some(ident) => match ident.to_string().as_str() {
                            "Vec" => {
                                self.vec.push(attr);
                            },
                            "Slice" => {
                                self.slice.push(attr);
                            },
                            "SliceMut" => {
                                self.slice_mut.push(attr);
                            },
                            "Ref" => {
                                self.ref_.push(attr);
                            },
                            "RefMut" => {
                                self.ref_mut.push(attr);
                            },
                            "Ptr" => {
                                self.ptr.push(attr);
                            },
                            "PtrMut" => {
                                self.ptr_mut.push(attr);
                            },
                            _ => panic!("expected a soa type, got {}", ident),
                        },
                        None => {
                            panic!("expected a soa type, got {}", quote!(#path));
                        }
                    },
                    _ => {
                        panic!("expected a soa type, got {}", quote!(#soa_type));
                    }
                };
            }
            _ => panic!("expected #[soa_attr(...)], got #[{}]", quote!(#meta)),
        }
    }

    /// Add a single trait from `#[soa_derive]`
    fn add_derive(&mut self, trait_: &str) {
        static EXCEPTIONS: &[&str] = &["Clone", "Deserialize", "Serialize"];

        let derive = create_derive_meta(trait_);
        if !EXCEPTIONS.contains(&trait_) {
            self.slice.push(derive.clone());
            self.slice_mut.push(derive.clone());
            self.ref_.push(derive.clone());
            self.ref_mut.push(derive.clone());
            self.ptr.push(derive.clone());
            self.ptr_mut.push(derive.clone());
        }

        // always add this derive to the Vec struct
        self.vec.push(derive);

        if trait_ == "Clone" {
            self.derive_clone = true;
        }
    }
}

fn create_derive_meta(name: &str) -> Meta {
    let mut nested = syn::punctuated::Punctuated::new();
    nested.push(NestedMeta::Meta(Meta::Path(Path::from(
        Ident::new(name, Span::call_site())
    ))));

    Meta::List(MetaList {
        path: Path::from(Ident::new("derive", Span::call_site())),
        paren_token: syn::token::Paren {span: Span::call_site()},
        nested: nested
    })
}

impl Input {
    pub fn new(input: DeriveInput) -> Input {
        let fields = match input.data {
            Data::Struct(s) => s.fields.iter().cloned().collect::<Vec<_>>(),
            _ => panic!("#[derive(StructOfArray)] only supports struct"),
        };

        if fields.is_empty() {
            panic!("#[derive(StructOfArray)] only supports struct with fields");
        }

        let mut extra_attrs = ExtraAttributes::new();

        for attr in input.attrs {
            if let Ok(meta) = attr.parse_meta() {
                if meta.path().is_ident("soa_derive") {
                    match meta {
                        Meta::NameValue(MetaNameValue {
                            lit: Lit::Str(string),
                            ..
                        }) => {
                            for value in string.value().split(',') {
                                let value = value.trim();
                                if value == "Copy" {
                                    panic!("can not derive Copy for SoA vectors");
                                }
                                extra_attrs.add_derive(value);
                            }
                        }
                        _ => panic!(
                            "expected #[soa_derive = \"Traits, To, Derive\"], got #[{}]",
                            quote!(#meta)
                        ),
                    }
                } else if meta.path().is_ident("soa_attr") {
                    extra_attrs.parse(&meta);
                }
            }
        }

        Input {
            name: input.ident,
            fields: fields,
            visibility: input.vis,
            attrs: extra_attrs,
        }
    }

    pub fn vec_name(&self) -> Ident {
        Ident::new(&format!("{}Vec", self.name), Span::call_site())
    }

    pub fn slice_name(&self) -> Ident {
        Ident::new(&format!("{}Slice", self.name), Span::call_site())
    }

    pub fn slice_mut_name(&self) -> Ident {
        Ident::new(&format!("{}SliceMut", self.name), Span::call_site())
    }

    pub fn ref_name(&self) -> Ident {
        Ident::new(&format!("{}Ref", self.name), Span::call_site())
    }

    pub fn ref_mut_name(&self) -> Ident {
        Ident::new(&format!("{}RefMut", self.name), Span::call_site())
    }

    pub fn ptr_name(&self) -> Ident {
        Ident::new(&format!("{}Ptr", self.name), Span::call_site())
    }

    pub fn ptr_mut_name(&self) -> Ident {
        Ident::new(&format!("{}PtrMut", self.name), Span::call_site())
    }
}
<|endoftext|>


<commit_before>/* diosix hypervisor's physical CPU core management
 *
 * (c) Chris Williams, 2019-2021.
 *
 * See LICENSE for usage and copying.
 */

/* Physical CPUs get their own private heaps to manage. Crucially, allocated memory
blocks can be shared by other CPUs. Any CPU can free any block, returning
it to its owner's heap pool. When allocating, a CPU can only draw from
its own heap, reusing any blocks freed by itself or other cores.

The hypervisor layer is unlikely to do much active allocation
so it's OK to keep it really simple for now. */

use super::lock::Mutex;
use hashbrown::hash_map::HashMap;
use platform::physmem::PhysMemSize;
use platform::cpu::{SupervisorState, CPUFeatures};
use platform::timer;
use super::vcore::{VirtualCore, VirtualCoreCanonicalID};
use super::scheduler::ScheduleQueues;
use super::capsule::{self, CapsuleID};
use super::message;
use super::heap;

/* physical CPU core IDs and count */
pub type PhysicalCoreID = usize;
pub type PhysicalCoreCount = PhysicalCoreID;

pub const BOOT_PCORE_ID: PhysicalCoreID = 0;
const PCORE_MAGIC: usize = 0xc001c0de;

/* require some help from the underlying platform */
extern "C"
{
    fn platform_cpu_private_variables() -> &'static mut PhysicalCore;
    fn platform_cpu_heap_base() -> *mut heap::HeapBlock;
    fn platform_cpu_heap_size() -> PhysMemSize;
    fn platform_save_supervisor_state(state: &SupervisorState);
    fn platform_load_supervisor_state(state: &SupervisorState);
}

lazy_static!
{
    /* map running virtual CPU cores to physical CPU cores, and vice-versa
    we can't store these in Core structs because it upsets Rust's borrow checker.
    note: PCORES keeps track of the last physical CPU core to run a given virtual
    core. this is more of a hint than a concrete guarantee: the virtual core
    may have been scheduled away, though it should be in the last physical
    CPU core's scheduling queue. */
    static ref VCORES: Mutex<HashMap<PhysicalCoreID, VirtualCore>> = Mutex::new("physical-virtual core table", HashMap::new());
    static ref PCORES: Mutex<HashMap<VirtualCoreCanonicalID, PhysicalCoreID>> = Mutex::new("physical-virtual core ID table", HashMap::new());
}

/* describe a physical CPU core - this structure is stored in the per-CPU private variable space.
   this is below the per-CPU machine-level stack */
#[repr(C)]
pub struct PhysicalCore
{
    /* this magic word is used to make sure the CPU's stack hasn't overflowed
    and corrupted this adjacent structure */
    magic: usize,

    /* every physical CPU core has a hardware-assigned ID number that may be non-linear,
    while the startup code assigns each core a linear ID number from zero. we keep a copy of that
    linear runtime-assigned ID here. the hardware-assigned ID is not used in the portable code */
    id: PhysicalCoreID,

    /* platform-defined bitmask of ISA features this core provides. if a virtual core has a features bit set that
    is unset in a physical core's feature bitmask, the virtual core will not be allowed to run on that physical core */
    features: CPUFeatures,

    /* each physical CPU core gets its own heap that it can share, but it must manage its own */
    pub heap: heap::Heap,

    /* each physical CPU gets its own set of queues of virtual CPU cores to schedule */
    queues: ScheduleQueues,

    /* can this run guest operating systems? or is it a system management core? true if it can run
    supervisor-mode code, false if not */
    smode: bool,

    /* set when this physical core CPU core last ran a scheduling decision */
    timer_sched_last: Option<timer::TimerValue>,

    /* set to true when the vcore running on this physical core is doomed.
       that means it's in a capsule that was restarted or killed and
       must not be saved after a context switch */
    vcore_doomed: bool
}

impl PhysicalCore
{
    /* intiialize a physical CPU core. Prepare it for running supervisor code.
    => id = diosix-assigned CPU core ID at boot time. this is separate from the hardware-assigned
            ID number, which may be non-linear. the runtime-generated core ID will
            run from zero to N-1 where N is the number of available cores */
    pub fn init(id: PhysicalCoreID)
    {
        /* the pre-hvmain startup code has allocated space for per-CPU core variables.
        this function returns a pointer to that structure */
        let mut cpu = PhysicalCore::this();

        cpu.magic = PCORE_MAGIC;
        cpu.id = id;
        cpu.features = platform::cpu::features();
        cpu.smode = platform::cpu::features_priv_check(platform::cpu::PrivilegeMode::Supervisor);
        cpu.timer_sched_last = None;
        cpu.vcore_doomed = false;

        let (heap_ptr, heap_size) = PhysicalCore::get_heap_config();
        cpu.heap.init(heap_ptr, heap_size);

        cpu.queues = ScheduleQueues::new();

        /* create a mailbox for messages from other cores */
        message::create_mailbox(id);
    }

    /* return pointer to the calling CPU core's fixed private data structure */
    pub fn this() -> &'static mut PhysicalCore
    {
        unsafe { platform_cpu_private_variables() }
    }

    /* return Ok if magic hasn't been overwritten, or the overwrite value as an error code */
    pub fn integrity_check() -> Result<(), usize>
    {
        match PhysicalCore::this().magic
        {
            PCORE_MAGIC => Ok(()),
            other => Err(other)
        }
    }

    /* return CPU heap base and size set aside by the pre-hvmain boot code */
    fn get_heap_config() -> (*mut heap::HeapBlock, PhysMemSize)
    {
        unsafe { (platform_cpu_heap_base(), platform_cpu_heap_size()) }
    }

    /* return boot-assigned ID number */
    pub fn get_id() -> PhysicalCoreID { PhysicalCore::this().id }

    /* return features bitmask */
    pub fn get_features() -> CPUFeatures { PhysicalCore::this().features }

    /* return a structure describing this core */
    pub fn describe() -> platform::cpu::CPUDescription { platform::cpu::CPUDescription }

    /* return a virtual CPU core awaiting to run on this physical CPU core */
    pub fn dequeue() -> Option<VirtualCore>
    {
        PhysicalCore::this().queues.dequeue()
    }

    /* move a virtual CPU core onto this physical CPU's queue of virtual cores to run */
    pub fn queue(to_queue: VirtualCore)
    {
        PhysicalCore::this().queues.queue(to_queue)
    }

    /* return true if able to run supervisor code. a system management core
    that cannot or is not expected to run guest workloads should return false */
    pub fn smode_supported() -> bool
    {
        PhysicalCore::this().smode
    }

    /* return ID of capsule of the virtual CPU core this physical CPU core is running, or None for none */
    pub fn get_capsule_id() -> Option<CapsuleID>
    {
        if let Some(vcore) = VCORES.lock().get(&PhysicalCore::get_id())
        {
            Some(vcore.get_capsule_id())
        }
        else
        {
            None
        }
    }

    /* mark the running vcore as doomed, meaning after it's context switched out,
    drop it. this is useful when killing or restarting capsules, and
    the current set of vcores needs to be flushed from the scheduling system */
    pub fn doom_vcore(&mut self) { self.vcore_doomed = true; }

    /* ensure the running vcore is not doomed */
    pub fn approve_vcore(&mut self) { self.vcore_doomed = false; }

    /* return true if vcore is doomed, ie: must be discarded */
    pub fn is_vcore_doomed(&self) -> bool { self.vcore_doomed }

    /* update the running virtual core's timer IRQ target. we have to do this here because
    the virtual core is held in a locked data structure. leaving this function relocks
    the structure. it's unsafe to access the vcore struct */
    pub fn set_virtualcore_timer_target(target: Option<timer::TimerValue>)
    {
        if let Some(vcore) = VCORES.lock().get_mut(&(PhysicalCore::get_id()))
        {
            vcore.set_timer_irq_at(target);
        }
    }

    /* get the virtual core's timer IRQ target */
    pub fn get_virtualcore_timer_target() -> Option<timer::TimerValue>
    {
        if let Some(vcore) = VCORES.lock().get_mut(&(PhysicalCore::get_id()))
        {
            return vcore.get_timer_irq_at();
        }
        None
    }

    /* return canonical ID for the virtual core running in the capsule on this CPU, if any */
    pub fn get_virtualcore_id(&self) -> Option<VirtualCoreCanonicalID>
    {
        let cid = match PhysicalCore::get_capsule_id()
        {
            Some(id) => id,
            None => return None
        };

        let vid = match VCORES.lock().get(&PhysicalCore::get_id())
        {
            Some(vcore) => vcore.get_id(),
            None => return None
        };

        Some(VirtualCoreCanonicalID
        {
            capsuleid: cid,
            vcoreid: vid
        })
    }

    /* set the exact per-CPU timer value of the last time this physical core make a scheduling decision */
    pub fn set_timer_sched_last(&mut self, value: Option<timer::TimerValue>)
    {
        self.timer_sched_last = value;
    }

    /* get the exact per-CPU timer value of the last time this physical core make a scheduling decision */
    pub fn get_timer_sched_last(&mut self) -> Option<timer::TimerValue>
    {
        self.timer_sched_last
    }
}

/* save current virtual CPU core's context, if we're running one, and load next virtual core's context.
this should be called from an IRQ context as it preserves the interrupted code's context
and overwrites the context with the next virtual core's context, so returning to supervisor
mode will land us in the new context */
pub fn context_switch(next: VirtualCore)
{
    let next_capsule = next.get_capsule_id();
    let pcore_id = PhysicalCore::get_id();

    /* find what this physical core was running, if anything */
    match VCORES.lock().remove(&pcore_id)
    {
        Some(current_vcore) =>
        {
            let current_capsule = current_vcore.get_capsule_id();

            /* if we're switching to a virtual CPU core in another capsule then replace the
            current hardware access permissions so that we're only allowing access to the RAM assigned
            to the next capsule to run */
            if current_capsule != next_capsule
            {
                capsule::enforce(next_capsule);
            }

            /* if the current virtual core isn't doomed, queue the vcore
               on the waiting list. if it is doomed, drop it */
            if PhysicalCore::this().is_vcore_doomed() == false
            {
                platform::cpu::save_supervisor_state(current_vcore.state_as_ref());
                PhysicalCore::queue(current_vcore);
            }
            else
            {
                drop(current_vcore);
            }
        },
        None =>
        {
            /* if we were not running a virtual CPU core then ensure we return to supervisor mode
            rather than hypervisor mode */
            platform::cpu::prep_supervisor_return();
            /* and enforce its hardware access permissions */
            capsule::enforce(next_capsule);
        }
    }

    /* prepare next virtual core to run when we leave this IRQ context */
    platform::cpu::load_supervisor_state(next.state_as_ref());

    /* link next virtual core and capsule to this physical CPU */
    PCORES.lock().insert(VirtualCoreCanonicalID
        {
            vcoreid: next.get_id(),
            capsuleid: next_capsule
        },
        pcore_id);

    /* and add the virtual core to the running virtual cores set.
       the previous vcore entry will be dropped */
    VCORES.lock().insert(pcore_id, next);

    /* and ensure this switched-in vcore is not doomed */
    PhysicalCore::this().approve_vcore();
}<commit_msg>Support saving floating-point state<commit_after>/* diosix hypervisor's physical CPU core management
 *
 * (c) Chris Williams, 2019-2021.
 *
 * See LICENSE for usage and copying.
 */

/* Physical CPUs get their own private heaps to manage. Crucially, allocated memory
blocks can be shared by other CPUs. Any CPU can free any block, returning
it to its owner's heap pool. When allocating, a CPU can only draw from
its own heap, reusing any blocks freed by itself or other cores.

The hypervisor layer is unlikely to do much active allocation
so it's OK to keep it really simple for now. */

use super::lock::Mutex;
use hashbrown::hash_map::HashMap;
use platform::physmem::PhysMemSize;
use platform::cpu::{SupervisorState, CPUFeatures};
use platform::timer;
use super::vcore::{VirtualCore, VirtualCoreCanonicalID};
use super::scheduler::ScheduleQueues;
use super::capsule::{self, CapsuleID};
use super::message;
use super::heap;

/* physical CPU core IDs and count */
pub type PhysicalCoreID = usize;
pub type PhysicalCoreCount = PhysicalCoreID;

pub const BOOT_PCORE_ID: PhysicalCoreID = 0;
const PCORE_MAGIC: usize = 0xc001c0de;

/* require some help from the underlying platform */
extern "C"
{
    fn platform_cpu_private_variables() -> &'static mut PhysicalCore;
    fn platform_cpu_heap_base() -> *mut heap::HeapBlock;
    fn platform_cpu_heap_size() -> PhysMemSize;
    fn platform_save_supervisor_state(state: &SupervisorState);
    fn platform_load_supervisor_state(state: &SupervisorState);
}

lazy_static!
{
    /* map running virtual CPU cores to physical CPU cores, and vice-versa
    we can't store these in Core structs because it upsets Rust's borrow checker.
    note: PCORES keeps track of the last physical CPU core to run a given virtual
    core. this is more of a hint than a concrete guarantee: the virtual core
    may have been scheduled away, though it should be in the last physical
    CPU core's scheduling queue. */
    static ref VCORES: Mutex<HashMap<PhysicalCoreID, VirtualCore>> = Mutex::new("physical-virtual core table", HashMap::new());
    static ref PCORES: Mutex<HashMap<VirtualCoreCanonicalID, PhysicalCoreID>> = Mutex::new("physical-virtual core ID table", HashMap::new());
}

/* describe a physical CPU core - this structure is stored in the per-CPU private variable space.
   this is below the per-CPU machine-level stack */
#[repr(C)]
pub struct PhysicalCore
{
    /* this magic word is used to make sure the CPU's stack hasn't overflowed
    and corrupted this adjacent structure */
    magic: usize,

    /* every physical CPU core has a hardware-assigned ID number that may be non-linear,
    while the startup code assigns each core a linear ID number from zero. we keep a copy of that
    linear runtime-assigned ID here. the hardware-assigned ID is not used in the portable code */
    id: PhysicalCoreID,

    /* platform-defined bitmask of ISA features this core provides. if a virtual core has a features bit set that
    is unset in a physical core's feature bitmask, the virtual core will not be allowed to run on that physical core */
    features: CPUFeatures,

    /* each physical CPU core gets its own heap that it can share, but it must manage its own */
    pub heap: heap::Heap,

    /* each physical CPU gets its own set of queues of virtual CPU cores to schedule */
    queues: ScheduleQueues,

    /* can this run guest operating systems? or is it a system management core? true if it can run
    supervisor-mode code, false if not */
    smode: bool,

    /* set when this physical core CPU core last ran a scheduling decision */
    timer_sched_last: Option<timer::TimerValue>,

    /* set to true when the vcore running on this physical core is doomed.
       that means it's in a capsule that was restarted or killed and
       must not be saved after a context switch */
    vcore_doomed: bool
}

impl PhysicalCore
{
    /* intiialize a physical CPU core. Prepare it for running supervisor code.
    => id = diosix-assigned CPU core ID at boot time. this is separate from the hardware-assigned
            ID number, which may be non-linear. the runtime-generated core ID will
            run from zero to N-1 where N is the number of available cores */
    pub fn init(id: PhysicalCoreID)
    {
        /* the pre-hvmain startup code has allocated space for per-CPU core variables.
        this function returns a pointer to that structure */
        let mut cpu = PhysicalCore::this();

        cpu.magic = PCORE_MAGIC;
        cpu.id = id;
        cpu.features = platform::cpu::features();
        cpu.smode = platform::cpu::features_priv_check(platform::cpu::PrivilegeMode::Supervisor);
        cpu.timer_sched_last = None;
        cpu.vcore_doomed = false;

        let (heap_ptr, heap_size) = PhysicalCore::get_heap_config();
        cpu.heap.init(heap_ptr, heap_size);

        cpu.queues = ScheduleQueues::new();

        /* create a mailbox for messages from other cores */
        message::create_mailbox(id);
    }

    /* return pointer to the calling CPU core's fixed private data structure */
    pub fn this() -> &'static mut PhysicalCore
    {
        unsafe { platform_cpu_private_variables() }
    }

    /* return Ok if magic hasn't been overwritten, or the overwrite value as an error code */
    pub fn integrity_check() -> Result<(), usize>
    {
        match PhysicalCore::this().magic
        {
            PCORE_MAGIC => Ok(()),
            other => Err(other)
        }
    }

    /* return CPU heap base and size set aside by the pre-hvmain boot code */
    fn get_heap_config() -> (*mut heap::HeapBlock, PhysMemSize)
    {
        unsafe { (platform_cpu_heap_base(), platform_cpu_heap_size()) }
    }

    /* return boot-assigned ID number */
    pub fn get_id() -> PhysicalCoreID { PhysicalCore::this().id }

    /* return features bitmask */
    pub fn get_features() -> CPUFeatures { PhysicalCore::this().features }

    /* return a structure describing this core */
    pub fn describe() -> platform::cpu::CPUDescription { platform::cpu::CPUDescription }

    /* return a virtual CPU core awaiting to run on this physical CPU core */
    pub fn dequeue() -> Option<VirtualCore>
    {
        PhysicalCore::this().queues.dequeue()
    }

    /* move a virtual CPU core onto this physical CPU's queue of virtual cores to run */
    pub fn queue(to_queue: VirtualCore)
    {
        PhysicalCore::this().queues.queue(to_queue)
    }

    /* return true if able to run supervisor code. a system management core
    that cannot or is not expected to run guest workloads should return false */
    pub fn smode_supported() -> bool
    {
        PhysicalCore::this().smode
    }

    /* return ID of capsule of the virtual CPU core this physical CPU core is running, or None for none */
    pub fn get_capsule_id() -> Option<CapsuleID>
    {
        if let Some(vcore) = VCORES.lock().get(&PhysicalCore::get_id())
        {
            Some(vcore.get_capsule_id())
        }
        else
        {
            None
        }
    }

    /* mark the running vcore as doomed, meaning after it's context switched out,
    drop it. this is useful when killing or restarting capsules, and
    the current set of vcores needs to be flushed from the scheduling system */
    pub fn doom_vcore(&mut self) { self.vcore_doomed = true; }

    /* ensure the running vcore is not doomed */
    pub fn approve_vcore(&mut self) { self.vcore_doomed = false; }

    /* return true if vcore is doomed, ie: must be discarded */
    pub fn is_vcore_doomed(&self) -> bool { self.vcore_doomed }

    /* update the running virtual core's timer IRQ target. we have to do this here because
    the virtual core is held in a locked data structure. leaving this function relocks
    the structure. it's unsafe to access the vcore struct */
    pub fn set_virtualcore_timer_target(target: Option<timer::TimerValue>)
    {
        if let Some(vcore) = VCORES.lock().get_mut(&(PhysicalCore::get_id()))
        {
            vcore.set_timer_irq_at(target);
        }
    }

    /* get the virtual core's timer IRQ target */
    pub fn get_virtualcore_timer_target() -> Option<timer::TimerValue>
    {
        if let Some(vcore) = VCORES.lock().get_mut(&(PhysicalCore::get_id()))
        {
            return vcore.get_timer_irq_at();
        }
        None
    }

    /* return canonical ID for the virtual core running in the capsule on this CPU, if any */
    pub fn get_virtualcore_id(&self) -> Option<VirtualCoreCanonicalID>
    {
        let cid = match PhysicalCore::get_capsule_id()
        {
            Some(id) => id,
            None => return None
        };

        let vid = match VCORES.lock().get(&PhysicalCore::get_id())
        {
            Some(vcore) => vcore.get_id(),
            None => return None
        };

        Some(VirtualCoreCanonicalID
        {
            capsuleid: cid,
            vcoreid: vid
        })
    }

    /* set the exact per-CPU timer value of the last time this physical core make a scheduling decision */
    pub fn set_timer_sched_last(&mut self, value: Option<timer::TimerValue>)
    {
        self.timer_sched_last = value;
    }

    /* get the exact per-CPU timer value of the last time this physical core make a scheduling decision */
    pub fn get_timer_sched_last(&mut self) -> Option<timer::TimerValue>
    {
        self.timer_sched_last
    }
}

/* save current virtual CPU core's context, if we're running one, and load next virtual core's context.
this should be called from an IRQ context as it preserves the interrupted code's context
and overwrites the context with the next virtual core's context, so returning to supervisor
mode will land us in the new context */
pub fn context_switch(next: VirtualCore)
{
    let next_capsule = next.get_capsule_id();
    let pcore_id = PhysicalCore::get_id();

    /* find what this physical core was running, if anything */
    match VCORES.lock().remove(&pcore_id)
    {
        Some(mut current_vcore) =>
        {
            let current_capsule = current_vcore.get_capsule_id();

            /* if we're switching to a virtual CPU core in another capsule then replace the
            current hardware access permissions so that we're only allowing access to the RAM assigned
            to the next capsule to run */
            if current_capsule != next_capsule
            {
                capsule::enforce(next_capsule);
            }

            /* if the current virtual core isn't doomed, queue the vcore
               on the waiting list. if it is doomed, drop it */
            if PhysicalCore::this().is_vcore_doomed() == false
            {
                /* handle core and FP registers separately to keep rust borrow checker happy with current_vcore */
                platform::cpu::save_supervisor_cpu_state(current_vcore.state_as_mut_ref());
                platform::cpu::save_supervisor_fp_state(current_vcore.fp_state_as_mut_ref());
                PhysicalCore::queue(current_vcore);
            }
            else
            {
                drop(current_vcore);
            }
        },
        None =>
        {
            /* if we were not running a virtual CPU core then ensure we return to supervisor mode
            rather than hypervisor mode */
            platform::cpu::prep_supervisor_return();
            /* and enforce its hardware access permissions */
            capsule::enforce(next_capsule);
        }
    }

    /* prepare next virtual core to run when we leave this IRQ context.
       this takes care of core registers and FP registers in one */
    platform::cpu::load_supervisor_cpu_fp_state
    (
        next.state_as_ref(),
        next.fp_state_as_ref()
    );

    /* link next virtual core and capsule to this physical CPU */
    PCORES.lock().insert(VirtualCoreCanonicalID
        {
            vcoreid: next.get_id(),
            capsuleid: next_capsule
        },
        pcore_id);

    /* and add the virtual core to the running virtual cores set.
       the previous vcore entry will be dropped */
    VCORES.lock().insert(pcore_id, next);

    /* and ensure this switched-in vcore is not doomed */
    PhysicalCore::this().approve_vcore();
}<|endoftext|>