Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,7 @@ pest_derive = "2.8.1"
llvm-sys = "201.0.1"
docopt = "1.1.1"
signal-hook = "0.3.18"

[features]
default = []
nightly = []

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need this feature?

29 changes: 22 additions & 7 deletions Containerfile
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
FROM registry.fedoraproject.org/fedora:43 as builder
FROM registry.fedoraproject.org/fedora:43 AS builder

ARG RUST_VERSION=stable

RUN dnf install -y \
rust \
cargo \
clippy \
rustfmt \
# for stub \
nasm \
# for script jit \
Expand All @@ -15,7 +13,19 @@ RUN dnf install -y \
# for bpf \
clang \
kernel-devel \
libbpf-devel
libbpf-devel && \
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | \
sh -s -- -y --default-toolchain $RUST_VERSION --profile minimal

# $HOME is not evaluated here, any better way of getting the toolchain
# directory?
ENV PATH="${PATH}:/root/.cargo/bin"

RUN rustup component add rustfmt clippy

RUN if [ "${RUST_VERSION}" == "nightly" ]; then \
rustup component add rust-src --toolchain nightly; \
fi

ADD ./ /berserker/

Expand All @@ -32,7 +42,12 @@ RUN cargo build -r
# Test will require stub binary to be available
ENV PATH="${PATH}:/berserker:/berserker/target/release"

RUN cargo test
RUN if [ "${RUST_VERSION}" == "nightly" ]; then \
TARGET=$(rustc --version --verbose | grep host | cut -d" " -f2) && \
RUSTFLAGS="-Z sanitizer=address" cargo +nightly test -Z build-std --target "$TARGET"; \
else \
cargo test; \
fi
Comment thread
Molter73 marked this conversation as resolved.

FROM registry.fedoraproject.org/fedora:43

Expand Down
4 changes: 3 additions & 1 deletion Containerfile.test
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
FROM berserker:latest
ARG RUST_VERSION=stable

FROM berserker-${RUST_VERSION}:latest

RUN dnf install -y \
which \
Expand Down
8 changes: 7 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,16 @@ endif

.PHONY: all
all:
docker build -t berserker -f Containerfile .
docker build -t berserker-stable -f Containerfile .
docker build -t berserker-test -f Containerfile.test .
docker run --privileged berserker-test

docker build -t berserker-nightly -f Containerfile --build-arg=RUST_VERSION=nightly .
docker build -t berserker-test -f Containerfile.test --build-arg=RUST_VERSION=nightly .
docker run --privileged berserker-test

docker tag berserker-stable berserker

.PHONY: build-network
build-berserker-network:
docker build -t berserker-network scripts/network
Expand Down
10 changes: 6 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ pub struct WorkloadConfig {
/// Custom workload configuration.
pub workload: Workload,

/// For how long to run the worker. Default value is zero, meaning no limit.
/// For how long to run the worker. Default value is zero, meaning no
/// limit.
#[serde(default = "default_duration")]
pub duration: u64,
}
Expand Down Expand Up @@ -194,8 +195,8 @@ pub enum Workload {
/// Maximum number of dynamic connections
connections_dyn_max: u32,

// How many connections to make to the same server address and port with
// different client ports
/// How many connections to make to the same server address and port
/// with different client ports
#[serde(default = "default_conns_per_addr")]
conns_per_addr: u16,

Expand All @@ -211,7 +212,8 @@ pub enum Workload {
/// Whether or not to wait for a connection to be removed before adding
/// a new one, when the dynamic connection limit is reached.
/// if true: an old connection will be forcibly removed
/// if false: wait for a connection to naturally age-off before adding a new one
/// if false: wait for a connection to naturally age-off before adding
/// a new one
preempt: bool,
},

Expand Down
6 changes: 4 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,8 @@ fn main() {
.required(false),
)
// Add in settings from the environment (with a prefix of APP)
// Eg.. `BERSERKER__WORKLOAD__ARRIVAL_RATE=1` would set the `arrival_rate` key
// Eg.. `BERSERKER__WORKLOAD__ARRIVAL_RATE=1` would set the
// `arrival_rate` key
.add_source(
config::Environment::with_prefix("BERSERKER")
.try_parsing(true)
Expand All @@ -230,7 +231,8 @@ fn main() {
let elapsed = duration_timer.elapsed().unwrap().as_secs();

// Ignore processes without specified duration -- we don't want
// neither terminate them, nor count against processes to compare.
// neither terminate them, nor count against processes to
// compare.
let watched_processes = processes
.iter()
.filter(|(_, duration)| *duration > 0)
Expand Down
98 changes: 70 additions & 28 deletions src/worker/script.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
extern crate llvm_sys as llvm;

use std::{
cell::RefCell,
collections::HashMap,
fmt::Display,
fs::OpenOptions,
Expand All @@ -23,7 +24,6 @@ use llvm::execution_engine::*;
use llvm::target::*;
use llvm_sys::LLVMType;
use llvm_sys::prelude::*;
use std::cell::RefCell;
use std::ffi::{CStr, CString, c_void};
use std::mem;

Expand Down Expand Up @@ -72,7 +72,7 @@ pub unsafe extern "C" fn debug(text: *const i8) -> u64 {
/// The caller must ensure the pointer is valid and points to a null
/// terminated C-string.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn open(path: *const i8) -> u64 {
pub unsafe extern "C" fn open_file(path: *const i8) -> u64 {
//let path = unsafe { CString::from_raw(path as *mut i8) };
let path = unsafe { CStr::from_ptr(path) };
debug!("Open path {:?}", path);
Expand Down Expand Up @@ -132,8 +132,7 @@ pub unsafe extern "C" fn task(name: *const i8, random: bool) -> u64 {
}

thread_local! {
static LAST_RANDOM_PATH: RefCell<CString> =
RefCell::new(CString::new("").unwrap());
static POINTERS: RefCell<Vec<*mut i8>> = const { RefCell::new(vec![]) };
}

/// Return a randomly generated path.
Expand All @@ -151,11 +150,24 @@ pub unsafe extern "C" fn random_path(base: *const i8) -> *const i8 {
.map(char::from)
.collect();

LAST_RANDOM_PATH.with(|last| {
let mut last = last.borrow_mut();
*last = CString::new(format!("{base}/{uniq}")).unwrap();
last.as_ptr()
})
let result = CString::new(format!("{base}/{uniq}")).unwrap().into_raw();
POINTERS.with(|ps| ps.borrow_mut().push(result));
result
}

/// # Safety
#[unsafe(no_mangle)]
pub unsafe extern "C" fn cleanup(_: *const i8) -> u64 {
POINTERS.with(|ps| {
let mut vec = ps.borrow_mut();
for p in vec.as_slice() {
let _ = unsafe { CString::from_raw(*p) };
}

vec.clear();
});

0
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -192,7 +204,7 @@ pub static RUNTIME: LazyLock<HashMap<String, RuntimeFunc>> =
(
"open".to_string(),
RuntimeFunc {
func: open as *const () as usize,
func: open_file as *const () as usize,
param_count: 1,
param_types: &[RuntimeType::Pointer],
return_type: RuntimeType::Int,
Expand All @@ -217,14 +229,27 @@ pub static RUNTIME: LazyLock<HashMap<String, RuntimeFunc>> =
return_type: RuntimeType::Pointer,
},
),
// utils
(
"cleanup".to_string(),
RuntimeFunc {
func: cleanup as *const () as usize,
param_count: 1,
param_types: &[RuntimeType::Pointer],
return_type: RuntimeType::Int,
},
),
])
});

impl ScriptWorker {
fn jit_instruction(name: String, arg: Arg, ctx: &BuildContext) {
fn jit_instruction(name: &CStr, arg: Arg, ctx: &BuildContext) {
let mut arg_ptr = Self::get_arg_value(arg, ctx);

let (func, func_type) = ctx.module_runtime.get(&name).unwrap();
let (func, func_type) = ctx
.module_runtime
.get(name.to_str().expect("Couldn't convert name to string"))
.unwrap();

unsafe {
LLVMBuildCall2(
Expand All @@ -233,7 +258,7 @@ impl ScriptWorker {
*func,
&mut arg_ptr,
1,
name.as_str().as_ptr() as *const _,
name.as_ptr() as *const _,
);
}
}
Expand Down Expand Up @@ -331,7 +356,8 @@ impl ScriptWorker {
&mut err,
) != 0
{
// In case of error, we must avoid using the uninitialized ExecutionEngineRef.
// In case of error, we must avoid using the uninitialized
// ExecutionEngineRef.
assert!(!err.is_null());
panic!(
"Failed to create execution engine: {:?}",
Expand Down Expand Up @@ -396,8 +422,8 @@ impl ScriptWorker {
function_type,
);

// Create a basic block in the function and set our builder to generate
// code in it.
// Create a basic block in the function and set our builder to
// generate code in it.
let bb = LLVMAppendBasicBlockInContext(
context,
function,
Expand Down Expand Up @@ -436,30 +462,22 @@ impl ScriptWorker {
// JIT the instruction and collect it's name
let name = match instr.clone() {
Instruction::Task { name, args: _ } => {
Self::jit_instruction(String::from("task"), name, &ctx);
Self::jit_instruction(c"task", name, &ctx);
"task"
}

Instruction::Open { path } => {
Self::jit_instruction(String::from("open"), path, &ctx);
Self::jit_instruction(c"open", path, &ctx);
"open"
}

Instruction::Ping { server } => {
Self::jit_instruction(
String::from("ping"),
server,
&ctx,
);
Self::jit_instruction(c"ping", server, &ctx);
"ping"
}

Instruction::Debug { text } => {
Self::jit_instruction(
String::from("debug"),
text,
&ctx,
);
Self::jit_instruction(c"debug", text, &ctx);
"debug"
}
};
Expand All @@ -483,6 +501,30 @@ impl ScriptWorker {
);
}

// Final instruction to clear dangling pointers
Self::jit_instruction(
c"cleanup",
Arg::Const {
text: "".to_string(),
},
&ctx,
);

let module_func = LLVMGetNamedFunction(
module,
c"cleanup".to_bytes().as_ptr() as *const _,
);

let runtime_func = &RUNTIME
.get("cleanup")
.expect("No runtime function with the name");

LLVMAddGlobalMapping(
ee,
module_func,
runtime_func.func as *mut c_void,
);

// Emit a `ret i64` into the function to return the computed sum.
let ret = LLVMConstInt(i64t, 0, 0);
LLVMBuildRet(builder, ret);
Expand Down
4 changes: 2 additions & 2 deletions src/worker/syscalls/ioctl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ pub struct IoctlCall {

impl IoctlCall {
pub fn new(_: &ArgsMap) -> Self {
// Zero initialize all fields, fd will be initialized in `Syscaller::init`.
// All other fields can be overridden as needed
// Zero initialize all fields, fd will be initialized in
// `Syscaller::init`. All other fields can be overridden as needed
Default::default()
}
}
Expand Down
Loading