Compare commits

..

8 Commits

@ -1,3 +1,4 @@
---
BasedOnStyle: Mozilla
IndentWidth: 8
Language: Cpp
@ -9,10 +10,10 @@ AlignConsecutiveMacros: true
AlignEscapedNewlines: Left
AlignTrailingComments: true
AllowShortBlocksOnASingleLine: Always
AllowShortBlocksOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: WithoutElse
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterReturnType: AllDefinitions
@ -37,7 +38,7 @@ BreakBeforeBinaryOperators: NonAssignment
ColumnLimit: 120
Cpp11BracedListStyle: true
Cpp11BracedListStyle: false
IndentCaseLabels: false
IndentWrappedFunctionNames: false
@ -46,9 +47,10 @@ KeepEmptyLinesAtTheStartOfBlocks: false
MaxEmptyLinesToKeep: 2
DerivePointerAlignment: false
PointerAlignment: Right
SortIncludes: true
SortIncludes: false
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true

@ -4,7 +4,7 @@ on: [push, pull_request]
env:
LLVM_VERSION: 13
WASI_SDK_VERSION: 12
WASI_SDK_URL: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz
WASI_SDK_PATH: /opt/wasi-sdk
LANG: C.UTF-8
LANGUAGE: C.UTF-8
@ -13,18 +13,18 @@ env:
# job control
jobs:
format:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- name: Apt Update
run: sudo apt-get update
- uses: actions/checkout@v2
- name: Install Clang Format
- name: Install LLVM
run: |
sudo ./install_llvm.sh $LLVM_VERSION
- name: Run Clang Format
- name: Clang Format
run: ./format.sh -d
test:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- name: Apt Update
run: sudo apt-get update
@ -62,7 +62,6 @@ jobs:
echo "/root/.cargo/bin:$PATH" >> $GITHUB_PATH
- name: Get wasi-sdk
run: |
WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-$WASI_SDK_VERSION/wasi-sdk-$WASI_SDK_VERSION.0-linux.tar.gz
wget $WASI_SDK_URL -O wasi-sdk.tar.gz
mkdir -p $WASI_SDK_PATH
tar xvfz wasi-sdk.tar.gz --strip-components=1 -C $WASI_SDK_PATH

@ -1,23 +1,24 @@
{
"configurations": [
{
"name": "Linux",
"intelliSenseMode": "clang-x64",
"includePath": [
"/usr/include/",
"${workspaceFolder}/runtime/include/",
"${workspaceFolder}/runtime/thirdparty/ck/include/",
"${workspaceFolder}/runtime/thirdparty/http-parser/",
"${workspaceFolder}/runtime/thirdparty/jsmn/",
"${workspaceFolder}/awsm/runtime/libc/wasi/include/",
"${workspaceFolder}/libsledge/include"
],
"defines": [
"x86_64",
"_GNU_SOURCE"
],
"cStandard": "c17"
}
],
"version": 4
}
"configurations": [
{
"name": "Linux",
"intelliSenseMode": "clang-x64",
"includePath": [
"/usr/include/",
"${workspaceFolder}/runtime/include/",
"${workspaceFolder}/runtime/thirdparty/ck/include/",
"${workspaceFolder}/runtime/thirdparty/http-parser/",
"${workspaceFolder}/runtime/thirdparty/jsmn/",
"${workspaceFolder}/awsm/runtime/libc/wasi/include/",
"${workspaceFolder}/libsledge/include"
],
"defines": [
"x86_64",
"_GNU_SOURCE"
],
"cStandard": "c17",
"compilerPath": "/usr/bin/clang"
}
],
"version": 4
}

@ -116,7 +116,7 @@
"tenant.h": "c",
"route_config.h": "c",
"http_router.h": "c",
"execution_histogram.h": "c",
"admissions_info.h": "c",
"tcp_server.h": "c",
"stdint.h": "c",
"scheduler_options.h": "c",
@ -126,38 +126,8 @@
"local_cleanup_queue.h": "c",
"sandbox_state_transition.h": "c",
"http_session_perf_log.h": "c",
"traffic_control.h": "c",
"memory_resource": "c",
"memory": "c",
"istream": "c",
"ostream": "c",
"sstream": "c",
"streambuf": "c",
"sandbox_perf_log.h": "c",
"global_request_scheduler_deque.h": "c",
"message.h": "c",
"dbf.h": "c",
"dbf_generic.h": "c",
"tenant_functions.h": "c",
"thread": "c",
"limits": "c",
"algorithm": "c",
"stdio.h": "c",
"get_time.h": "c",
"unistd.h": "c",
"wasi.h": "c",
"stat.h": "c",
"functional": "c",
"sandbox_state.h": "c",
"ratio": "c",
"tuple": "c",
"type_traits": "c",
"perf_window.h": "c",
"http_route_total.h": "c",
"sledge_abi_symbols.h": "c",
"mutex": "c",
"lock.h": "c",
"route_latency.h": "c"
"global_request_scheduler_deque.h": "c"
},
"files.exclude": {
"**/.git": true,
@ -219,6 +189,5 @@
"TKILL",
"WASI"
],
"C_Cpp.errorSquiggles": "Enabled",
"C_Cpp.default.compilerPath": "/usr/bin/clang"
"C_Cpp.errorSquiggles": "Enabled"
}

@ -1,12 +1,9 @@
# using ubuntu 20 docker image
FROM ubuntu:focal
ENV LLVM_VERSION=13
ENV WASI_SDK_VERSION=12
ARG DEBIAN_FRONTEND=noninteractive
ARG HEY_URL=https://hey-release.s3.us-east-2.amazonaws.com/hey_linux_amd64
ARG WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-$WASI_SDK_VERSION/wasi-sdk_$WASI_SDK_VERSION.0_amd64.deb
ARG WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk_12.0_amd64.deb
ARG SHFMT_URL=https://github.com/mvdan/sh/releases/download/v3.2.4/shfmt_v3.2.4_linux_amd64
ARG SHELLCHECK_URL=https://github.com/koalaman/shellcheck/releases/download/stable/shellcheck-stable.linux.x86_64.tar.xz
@ -77,11 +74,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
vim \
wabt
ENV LLVM_VERSION=12
ADD install_llvm.sh /sledge/install_llvm.sh
RUN ./sledge/install_llvm.sh $LLVM_VERSION
# WASI-SDK
RUN curl -sS -L -O $WASI_SDK_URL && dpkg -i wasi-sdk_$WASI_SDK_VERSION.0_amd64.deb && rm -f wasi-sdk_$WASI_SDK_VERSION.0_amd64.deb
RUN curl -sS -L -O $WASI_SDK_URL && dpkg -i wasi-sdk_12.0_amd64.deb && rm -f wasi-sdk_12.0_amd64.deb
ENV WASI_SDK_PATH=/opt/wasi-sdk
# Create non-root user and add to sudoers

@ -26,12 +26,15 @@ all: \
gps_ekf.install \
license_plate_detection.install \
resize_image.install \
cnn_face_detection.install \
get_jpeg_resolution.install \
scratch_storage_get.install \
scratch_storage_set.install \
scratch_storage_delete.install \
scratch_storage_upsert.install \
.PHONY: clean
clean:
@make -C wasm_apps clean
@make -C scratch_storage clean
@rm -rf dist
@rm -rf ../runtime/bin/*.so
@ -65,7 +68,7 @@ dist/%.bc: ./wasm_apps/dist/%.wasm dist
${AWSMCC} ${AWSMFLAGS} $< -o $@
dist/%.ll: dist/%.bc
llvm-dis $< -o $@
llvm-dis-12 $< -o $@
dist/%.wasm.so: dist/%.bc
${CC} ${CFLAGS} ${LDFLAGS} $^ -o $@
@ -102,12 +105,6 @@ gps_ekf.install: ../runtime/bin/gps_ekf.wasm.so
.PHONY: license_plate_detection.install
license_plate_detection.install: ../runtime/bin/license_plate_detection.wasm.so
.PHONY: cnn_face_detection.install
cnn_face_detection.install: ../runtime/bin/cnn_face_detection.wasm.so
.PHONY: get_jpeg_resolution.install
get_jpeg_resolution.install: ../runtime/bin/get_jpeg_resolution.wasm.so
.PHONY: trap_divzero.install
trap_divzero.install: ../runtime/bin/trap_divzero.wasm.so

@ -1 +1 @@
Subproject commit 272fcf42b6559ccb5c5213eb78edfc0f703520ab
Subproject commit 69c8b6116664d65a851cc459601bef6af3caeaea

@ -1,9 +1,7 @@
#!/bin/bash
LLVM_VERSION=13
validate() {
utility="clang-format"
utility="clang-format-13"
utility_version="$("$utility" --version 2> /dev/null)" || {
echo "$utility not found in path!"
exit 1
@ -13,7 +11,7 @@ validate() {
declare -i major=0
declare -i minor=0
declare -i patch=0
declare -i required_major=$LLVM_VERSION
declare -i required_major=13
declare -i required_minor=0
declare -i required_patch=0
@ -45,14 +43,14 @@ help() {
dry_run() {
find runtime \
\( -path "runtime/thirdparty" \) -prune -false -o \
-type f \( -iname \*.h -o -iname \*.c -o -iname \*.s \) -print0 \
| xargs --null clang-format -Werror -n -ferror-limit=1
\( -path "runtime/thirdparty" -o -path "applications/gocr" -o -path "applications/TinyEKF" -o -path "applications/CMSIS_5_NN" -o -path "applications/sod" -o -path "applications/**/thirdparty" \) -prune -false -o \
-type f \( -iname \*.h -o -iname \*.c -o -iname \*.s \) -print \
| xargs clang-format -Werror -n -ferror-limit=0
}
format() {
find runtime \
\( -path "runtime/thirdparty" \) -prune -false -o \
\( -path "runtime/thirdparty" -o -path "applications/gocr" -o -path "applications/TinyEKF" -o -path "applications/CMSIS_5_NN" -o -path "applications/sod" -o -path "applications/**/thirdparty" \) -prune -false -o \
-type f \( -iname \*.h -o -iname \*.c -o -iname \*.s \) -print0 \
| xargs --null clang-format -i
}

@ -1,18 +1,15 @@
#!/bin/bash
# Note, wasi-sdk versions do NOT match llvm versions, e.g. wasi-sdk-12 actually uses llvm-11
LLVM_VERSION=13
WASI_SDK_VERSION=12
LLVM_VERSION=12
ARCH=$(uname -m)
ARCH=$(uname -p)
if [[ $ARCH = "x86_64" ]]; then
SHFMT_URL=https://github.com/mvdan/sh/releases/download/v3.4.3/shfmt_v3.4.3_linux_amd64
WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-$WASI_SDK_VERSION/wasi-sdk_$WASI_SDK_VERSION.0_amd64.deb
WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk_12.0_amd64.deb
elif [[ $ARCH = "aarch64" ]]; then
SHFMT_URL=https://github.com/patrickvane/shfmt/releases/download/master/shfmt_linux_arm
echo "ARM64 support is still a work in progress!"
exit 1
else
echo "This script only supports x86_64 and aarch64"
exit 1
@ -66,8 +63,6 @@ wget $SHFMT_URL -O shfmt && chmod +x shfmt && sudo mv shfmt /usr/local/bin/shfmt
sudo ./install_llvm.sh $LLVM_VERSION
curl -sS -L -O $WASI_SDK_URL && sudo dpkg -i wasi-sdk_$WASI_SDK_VERSION.0_amd64.deb && rm -f wasi-sdk_$WASI_SDK_VERSION.0_amd64.deb
if [ -z "${WASI_SDK_PATH}" ]; then
export WASI_SDK_PATH=/opt/wasi-sdk
echo "export WASI_SDK_PATH=/opt/wasi-sdk" >> ~/.bashrc

@ -8,28 +8,28 @@ echo "Installing LLVM $LLVM_VERSION"
# Script Installs clang, lldb, lld, and clangd
curl --proto '=https' --tlsv1.2 -sSf https://apt.llvm.org/llvm.sh | bash -s -- "$LLVM_VERSION"
# Installing "libc++-xx-dev" automagically installs "libc++1-xx", "libunwind-xx" and "libunwind-xx-dev"
apt-get install -y --no-install-recommends \
"libc++-$LLVM_VERSION-dev" \
"libc++abi-$LLVM_VERSION-dev" \
"libc++1-$LLVM_VERSION" \
"libunwind-$LLVM_VERSION" \
"libunwind-$LLVM_VERSION-dev" \
"clang-tools-$LLVM_VERSION" \
"clang-tidy-$LLVM_VERSION" \
"clang-format-$LLVM_VERSION"
update-alternatives --remove-all wasm-ld
update-alternatives --remove-all llvm-config
update-alternatives --remove-all llvm-objdump
update-alternatives --remove-all llvm-dis
update-alternatives --remove-all clang-format
update-alternatives --remove-all clang
update-alternatives --remove-all clang++
update-alternatives --remove-all clang-tidy
sudo update-alternatives --remove-all clang-format
sudo update-alternatives --remove-all clang
sudo update-alternatives --remove-all clang++
sudo update-alternatives --remove-all llvm-config
sudo update-alternatives --remove-all llvm-objdump
sudo update-alternatives --remove-all llvm-objdump
sudo update-alternatives --remove-all clang-tidy
update-alternatives --install /usr/bin/wasm-ld wasm-ld "/usr/bin/wasm-ld-$LLVM_VERSION" 100
update-alternatives --install /usr/bin/llvm-config llvm-config "/usr/bin/llvm-config-$LLVM_VERSION" 100
update-alternatives --install /usr/bin/llvm-objdump llvm-objdump "/usr/bin/llvm-objdump-$LLVM_VERSION" 100
update-alternatives --install /usr/bin/llvm-dis llvm-dis /usr/bin/llvm-dis-$LLVM_VERSION 100
update-alternatives --install /usr/bin/clang-format clang-format "/usr/bin/clang-format-$LLVM_VERSION" 100
update-alternatives --install /usr/bin/clang clang "/usr/bin/clang-$LLVM_VERSION" 100
update-alternatives --install /usr/bin/clang++ clang++ "/usr/bin/clang++-$LLVM_VERSION" 100
update-alternatives --install /usr/bin/llvm-config llvm-config "/usr/bin/llvm-config-$LLVM_VERSION" 100
update-alternatives --install /usr/bin/llvm-objdump llvm-objdump "/usr/bin/llvm-objdump-$LLVM_VERSION" 100
update-alternatives --install /usr/bin/clang-tidy clang-tidy "/usr/bin/clang-tidy-$LLVM_VERSION" 100
update-alternatives --install /usr/bin/wasm-ld wasm-ld "/usr/bin/wasm-ld-$LLVM_VERSION" 100

@ -2,7 +2,7 @@ CFILES := src/*.c
INCLUDES := -Iinclude/
# fPIC = Position Independent Code, necessary for linking to relative addresses.
CFLAGS := -fPIC -O3 -flto -ftls-model=initial-exec
CFLAGS := -fPIC -O3 -flto
# Strips out calls to assert() and disables debuglog
CFLAGS+=-DNDEBUG

@ -38,10 +38,6 @@ BINARY_NAME=sledgert
# Feature Toggles
CFLAGS += -DEXECUTION_HISTOGRAM
# CFLAGS += -DEXECUTION_REGRESSION
# It is recommended (not mandatory) to enable this flag along with the EXECUTION_HISTOGRAM flag:
# CFLAGS += -DADMISSIONS_CONTROL
# Debugging Flags
@ -60,7 +56,6 @@ CFLAGS += -DEXECUTION_HISTOGRAM
# CFLAGS += -DLOG_TO_FILE
# Various Informational Logs for Debugging
# CFLAGS += -DLOG_EXECUTION_HISTOGRAM
# CFLAGS += -DLOG_ADMISSIONS_CONTROL
# CFLAGS += -DLOG_CONTEXT_SWITCHES
# CFLAGS += -DLOG_HTTP_PARSER
@ -99,7 +94,7 @@ CFLAGS += -DEXECUTION_HISTOGRAM
# This flag tracks the total number of sandboxes in the various states
# It is useful to debug if sandboxes are "getting caught" in a particular state
# CFLAGS += -DSANDBOX_STATE_TOTALS
CFLAGS += -DSANDBOX_STATE_TOTALS
# This flag enables an per-worker atomic count of sandbox's local runqueue count in thread local storage
# Useful to debug if sandboxes are "getting caught" or "leaking" while in a local runqueue

@ -1,19 +1,18 @@
#pragma once
#ifdef ADMISSIONS_CONTROL
#include <stdbool.h>
#include <stdint.h>
#ifdef ADMISSIONS_CONTROL
#define ADMISSIONS_CONTROL_GRANULARITY 1000000
extern _Atomic uint64_t admissions_control_admitted;
extern uint64_t admissions_control_capacity;
#endif
void admissions_control_initialize(void);
void admissions_control_add(uint64_t admissions_estimate);
void admissions_control_subtract(uint64_t admissions_estimate);
uint64_t admissions_control_calculate_estimate(uint64_t estimated_execution, uint64_t relative_deadline);
uint64_t admissions_control_calculate_estimate_us(uint32_t estimated_execution_us, uint32_t relative_deadline_us);
void admissions_control_log_decision(uint64_t admissions_estimate, bool admitted);
uint64_t admissions_control_decide(uint64_t admissions_estimate);
#endif

@ -0,0 +1,15 @@
#pragma once
#include "perf_window_t.h"
struct admissions_info {
struct perf_window perf_window;
uint8_t percentile; /* 50 - 99 */
int control_index; /* Precomputed Lookup index when perf_window is full */
uint64_t estimate; /* cycles */
uint64_t relative_deadline; /* Relative deadline in cycles. This is duplicated state */
};
void admissions_info_initialize(struct admissions_info *admissions_info, uint8_t percentile,
uint64_t expected_execution, uint64_t relative_deadline);
void admissions_info_update(struct admissions_info *admissions_info, uint64_t execution_duration);

@ -4,7 +4,6 @@
#include <assert.h>
#include "arch/common.h"
#include "current_sandbox.h"
#define ARCH_SIG_JMP_OFF 0x100 /* Based on code generated! */
@ -47,24 +46,20 @@ arch_context_switch(struct arch_context *a, struct arch_context *b)
* Assumption: In the case of a slow context switch, the caller
* set current_sandbox to the sandbox containing the target context
*/
if (b->variant == ARCH_CONTEXT_VARIANT_SLOW) {
/*if (b->variant == ARCH_CONTEXT_VARIANT_SLOW) {
struct sandbox *current = current_sandbox_get();
assert(current != NULL && b == &current->ctxt);
}
}*/
#endif
/* if both a and b are NULL, there is no state change */
assert(a != NULL || b != NULL);
assert(a != NULL && b != NULL);
/* Assumption: The caller does not switch to itself */
assert(a != b);
/* Set any NULLs to worker_thread_base_context to resume execution of main */
if (a == NULL) a = &worker_thread_base_context;
if (b == NULL) b = &worker_thread_base_context;
/* A Transition {Unused, Running} -> Fast */
assert(a->variant == ARCH_CONTEXT_VARIANT_UNUSED || a->variant == ARCH_CONTEXT_VARIANT_RUNNING);
assert(a->variant == ARCH_CONTEXT_VARIANT_RUNNING);
/* B Transition {Fast, Slow} -> Running */
assert(b->variant == ARCH_CONTEXT_VARIANT_FAST || b->variant == ARCH_CONTEXT_VARIANT_SLOW);
@ -87,6 +82,8 @@ arch_context_switch(struct arch_context *a, struct arch_context *b)
"ldr x1, [%[bv]]\n\t"
"sub x1, x1, #2\n\t"
"cbz x1, slow%=\n\t"
"mov x3, #3\n\t"
"str x3, [%[bv]]\n\t" /* b->variant = ARCH_CONTEXT_VARIANT_RUNNING; */
"ldr x0, [%[b]]\n\t"
"ldr x1, [%[b], 8]\n\t"
"mov sp, x0\n\t"
@ -95,8 +92,6 @@ arch_context_switch(struct arch_context *a, struct arch_context *b)
"br %[slowpath]\n\t"
".align 8\n\t"
"reset%=:\n\t"
"mov x1, #3\n\t"
"str x1, [%[bv]]\n\t"
".align 8\n\t"
"exit%=:\n\t"
:
@ -109,6 +104,37 @@ arch_context_switch(struct arch_context *a, struct arch_context *b)
return 0;
}
/**
* Load a new sandbox that preempted an existing sandbox, restoring only the
* instruction pointer and stack pointer registers.
* @param active_context - the context of the current worker thread
* @param sandbox_context - the context that we want to restore
*/
static inline void
arch_context_restore_fast(mcontext_t *active_context, struct arch_context *sandbox_context)
{
assert(active_context != NULL);
assert(sandbox_context != NULL);
/* Assumption: Base Context is only ever used by arch_context_switch */
assert(sandbox_context != &worker_thread_base_context);
assert(sandbox_context->regs[UREG_SP]);
assert(sandbox_context->regs[UREG_IP]);
/* Transitioning from Fast -> Running */
assert(sandbox_context->variant == ARCH_CONTEXT_VARIANT_FAST);
sandbox_context->variant = ARCH_CONTEXT_VARIANT_RUNNING;
//active_context->gregs[REG_RSP] = sandbox_context->regs[UREG_SP];
//active_context->gregs[REG_RIP] = sandbox_context->regs[UREG_IP];
active_context->sp = sandbox_context->regs[UREG_SP];
active_context->pc = sandbox_context->regs[UREG_IP];
}
#else
#warning "Neither AARCH64 nor aarch64 was defined, but aarch64/context.h was included!"
#endif

@ -3,9 +3,9 @@
#include <setjmp.h>
#include <ucontext.h>
#include "arch/arch_context_variant_t.h"
#include "arch/reg_t.h"
#include "arch/ureg_t.h"
#include "arch/arch_context_variant_t.h"
struct arch_context {
arch_context_variant_t variant;

@ -1,6 +1,5 @@
#pragma once
#include "likely.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@ -11,6 +10,12 @@ struct auto_buf {
size_t size;
};
static inline void auto_buf_copy(struct auto_buf *dest, struct auto_buf *source) {
if (dest == NULL || source == NULL) return;
fwrite(source->data, 1, source->size, dest->handle);
fflush(dest->handle);
}
static inline int
auto_buf_init(struct auto_buf *buf)
{

@ -3,7 +3,6 @@
#include <threads.h>
#include "current_wasm_module_instance.h"
#include "listener_thread.h"
#include "sandbox_types.h"
/* current sandbox that is active.. */
@ -31,25 +30,24 @@ current_sandbox_set(struct sandbox *sandbox)
/* Unpack hierarchy to avoid pointer chasing */
if (sandbox == NULL) {
sledge_abi__current_wasm_module_instance = (struct wasm_module_instance){
/* Public */
.abi =
(struct sledge_abi__wasm_module_instance){
.memory =
(struct sledge_abi__wasm_memory){
.size = 0,
.capacity = 0,
.max = 0,
.buffer = NULL,
},
.table = NULL,
.wasmg_0 = 0,
},
/* Private */
.wasi_context = NULL,
/* Public */
.abi =
(struct sledge_abi__wasm_module_instance){
.memory =
(struct sledge_abi__wasm_memory){
.size = 0,
.capacity = 0,
.max = 0,
.buffer = NULL,
},
.table = NULL,
.wasmg_0 = 0,
},
/* Private */
.wasi_context = NULL,
};
worker_thread_current_sandbox = NULL;
/* This is because the event core does not maintain core-assigned deadline */
if (!listener_thread_is_running()) runtime_worker_threads_deadline[worker_thread_idx] = UINT64_MAX;
worker_thread_current_sandbox = NULL;
runtime_worker_threads_deadline[worker_thread_idx] = UINT64_MAX;
} else {
sledge_abi__current_wasm_module_instance.wasi_context = sandbox->wasi_context;
memcpy(&sledge_abi__current_wasm_module_instance.abi.memory, &sandbox->memory->abi,
@ -57,9 +55,8 @@ current_sandbox_set(struct sandbox *sandbox)
sledge_abi__current_wasm_module_instance.abi.table = sandbox->module->indirect_table;
wasm_globals_update_if_used(&sandbox->globals, 0,
&sledge_abi__current_wasm_module_instance.abi.wasmg_0);
worker_thread_current_sandbox = sandbox;
if (!listener_thread_is_running())
runtime_worker_threads_deadline[worker_thread_idx] = sandbox->absolute_deadline;
worker_thread_current_sandbox = sandbox;
runtime_worker_threads_deadline[worker_thread_idx] = sandbox->absolute_deadline;
}
}

@ -1,14 +0,0 @@
#pragma once
#include "perf_window_t.h"
struct execution_histogram {
struct perf_window perf_window;
uint8_t percentile; /* 50 - 99 */
int control_index; /* Precomputed Lookup index when perf_window is full */
uint64_t estimated_execution; /* cycles */
};
void execution_histogram_initialize(struct execution_histogram *execution_histogram, uint8_t percentile,
uint64_t expected_execution);
void execution_histogram_update(struct execution_histogram *execution_histogram, uint64_t execution_duration);

@ -1,26 +0,0 @@
#pragma once
#ifdef EXECUTION_REGRESSION
#include "http_session.h"
#include <stdint.h>
static inline uint64_t
get_regression_prediction(struct http_session *session)
{
/* Default Pre-processing - Extract payload size */
const int payload_size = session->http_request.body_length;
const double regression_params[2] = {payload_size, session->regression_param};
/* Perform Linear Regression using the factors provided by the regressor performed AoT on Matlab using training
* tenant-given dataset */
const struct regression_model model = session->route->regr_model;
const uint64_t prediction = (regression_params[0] / model.scale * model.beta1
+ regression_params[1] / model.scale * model.beta2)
+ model.bias;
return prediction;
}
#endif

@ -12,11 +12,28 @@ struct http_header {
int value_length;
};
static inline void http_header_copy(struct http_header *dest, struct http_header *source) {
if (source == NULL || dest == NULL) return;
dest->key = (char*) malloc (source->key_length);
memcpy(dest->key, source->key, source->key_length);
dest->key_length = source->key_length;
dest->value = (char*) malloc (source->value_length);
memcpy(dest->value, source->value, source->value_length);
dest->value_length = source->value_length;
}
struct http_query_param {
char value[HTTP_MAX_QUERY_PARAM_LENGTH];
int value_length;
};
static inline void http_query_param_copy(struct http_query_param *dest, struct http_query_param *source) {
if (source == NULL || dest == NULL) return;
memcpy(dest->value, source->value, HTTP_MAX_QUERY_PARAM_LENGTH);
dest->value_length = source->value_length;
}
struct http_request {
char full_url[HTTP_MAX_FULL_URL_LENGTH];
struct http_header headers[HTTP_MAX_HEADER_COUNT];
@ -40,4 +57,29 @@ struct http_request {
int cursor; /* Sandbox cursor (offset from body pointer) */
};
static inline void http_request_copy(struct http_request *dest, struct http_request *source) {
if (dest == NULL || source == NULL) return;
memcpy(dest->full_url, source->full_url, HTTP_MAX_FULL_URL_LENGTH);
for (int i = 0; i < HTTP_MAX_HEADER_COUNT; i++) {
http_header_copy(&(dest->headers[i]), &(source->headers[i]));
}
dest->header_count = source->header_count;
dest->method = source->method;
for (int i = 0; i < HTTP_MAX_QUERY_PARAM_COUNT; i++) {
http_query_param_copy(&(dest->query_params[i]), &(source->query_params[i]));
}
dest->query_params_count = source->query_params_count;
dest->body = (char*) malloc (source->body_length);
memcpy(dest->body, source->body, source->body_length);
dest->body_length = source->body_length;
dest->body_length_read = source->body_length_read;
dest->length_parsed = source->length_parsed;
dest->last_was_value = source->last_was_value;
dest->header_end = source->header_end;
dest->message_begin = source->message_begin;
dest->message_end = source->message_end;
}
void http_request_print(struct http_request *http_request);

@ -1,12 +1,14 @@
#pragma once
#include <stdlib.h>
#include <string.h>
#include "http.h"
#include "module.h"
#include "route_latency.h"
#include "route.h"
#include "route_config.h"
#include "route_latency.h"
#include "vec.h"
#include <stdlib.h>
typedef struct route route_t;
VEC(route_t)
@ -20,8 +22,7 @@ http_router_init(http_router_t *router, size_t capacity)
}
static inline int
http_router_add_route(http_router_t *router, struct route_config *config, struct module *module,
struct module *module_proprocess)
http_router_add_route(http_router_t *router, struct route_config *config, struct module *module)
{
assert(router != NULL);
assert(config != NULL);
@ -29,35 +30,20 @@ http_router_add_route(http_router_t *router, struct route_config *config, struct
assert(config->route != NULL);
assert(config->http_resp_content_type != NULL);
struct route route = {.route = config->route,
.module = module,
.relative_deadline_us = config->relative_deadline_us,
.relative_deadline = (uint64_t)config->relative_deadline_us * runtime_processor_speed_MHz,
.response_content_type = config->http_resp_content_type};
struct route route = { .route = config->route,
.module = module,
.relative_deadline_us = config->relative_deadline_us,
.relative_deadline = (uint64_t)config->relative_deadline_us
* runtime_processor_speed_MHz,
.response_content_type = config->http_resp_content_type };
route_latency_init(&route.latency);
http_route_total_init(&route.metrics);
#ifdef EXECUTION_REGRESSION
/* Execution Regression setup */
route.module_proprocess = module_proprocess;
route.regr_model.bias = config->model_bias / 1000.0;
route.regr_model.scale = config->model_scale / 1000.0;
route.regr_model.num_of_param = config->model_num_of_param;
route.regr_model.beta1 = config->model_beta1 / 1000.0;
route.regr_model.beta2 = config->model_beta2 / 1000.0;
#endif
const uint64_t expected_execution = route.relative_deadline / 2;
#ifdef ADMISSIONS_CONTROL
/* Addmissions Control setup */
route.execution_histogram.estimated_execution = expected_execution;
#endif
#ifdef EXECUTION_HISTOGRAM
/* Execution Histogram setup */
execution_histogram_initialize(&route.execution_histogram, config->admissions_percentile, expected_execution);
#endif
/* Admissions Control */
uint64_t expected_execution = (uint64_t)config->expected_execution_us * runtime_processor_speed_MHz;
admissions_info_initialize(&route.admissions_info, config->admissions_percentile, expected_execution,
route.relative_deadline);
int rc = vec_route_t_push(router, route);
if (unlikely(rc == -1)) { return -1; }

@ -22,6 +22,7 @@
#include "tcp_session.h"
#include "tenant.h"
enum http_session_state
{
HTTP_SESSION_UNINITIALIZED = 0,
@ -57,13 +58,24 @@ struct http_session {
uint64_t request_downloaded_timestamp;
uint64_t response_takeoff_timestamp;
uint64_t response_sent_timestamp;
bool did_preprocessing;
uint64_t preprocessing_duration;
double regression_param; /* Calculated in tenant preprocessing logic if provided */
};
static inline void http_session_copy(struct http_session *dest, struct http_session *source) {
if (dest == NULL || source == NULL) return;
dest->tag = source->tag;
http_request_copy(&dest->http_request, &source->http_request);
auto_buf_copy(&dest->request_buffer, &source->request_buffer);
auto_buf_copy(&dest->response_header, &source->response_header);
dest->response_header_written = source->response_header_written;
auto_buf_copy(&dest->response_body, &source->response_body);
dest->response_body_written = source->response_body_written;
dest->route = source->route;
}
extern void http_session_perf_log_print_entry(struct http_session *http_session);
/**
* Initalize state associated with an http parser
* Because the http_parser structure uses pointers to the request buffer, if realloc moves the request
@ -105,6 +117,7 @@ http_session_init(struct http_session *session, int socket_descriptor, const str
/* Defer initializing response_body until we've matched a route */
auto_buf_init(&session->response_header);
session->state = HTTP_SESSION_INITIALIZED;
@ -115,14 +128,23 @@ static inline int
http_session_init_response_body(struct http_session *session)
{
assert(session != NULL);
assert(session->response_body.data == NULL);
assert(session->response_body.size == 0);
assert(session->response_body_written == 0);
int rc = auto_buf_init(&session->response_body);
if (rc < 0) {
auto_buf_deinit(&session->request_buffer);
return -1;
//assert(session->response_body.data == NULL);
//assert(session->response_body.size == 0);
//assert(session->response_body_written == 0);
//int rc = auto_buf_init(&session->response_body);
//if (rc < 0) {
// auto_buf_deinit(&session->request_buffer);
// return -1;
//}
session->response_body.size = 0;
session->response_body_written = 0;
if (session->response_body.data == NULL) {
int rc = auto_buf_init(&session->response_body);
if (rc < 0) {
auto_buf_deinit(&session->request_buffer);
return -1;
}
}
return 0;
@ -156,9 +178,9 @@ http_session_deinit(struct http_session *session)
{
assert(session);
auto_buf_deinit(&session->request_buffer);
auto_buf_deinit(&session->response_header);
auto_buf_deinit(&session->response_body);
//auto_buf_deinit(&session->request_buffer);
//auto_buf_deinit(&session->response_header);
//auto_buf_deinit(&session->response_body);
}
static inline void
@ -166,8 +188,8 @@ http_session_free(struct http_session *session)
{
assert(session);
http_session_deinit(session);
free(session);
//http_session_deinit(session);
//free(session);
}
/**
@ -268,7 +290,7 @@ http_session_send_response_body(struct http_session *session, void_star_cb on_ea
/* Assumption: Already flushed in order to write content-length to header */
// TODO: Test if body is empty
printf("body is %s\n", session->response_body.data);
while (session->response_body_written < session->response_body.size) {
ssize_t sent =
tcp_session_send(session->socket,
@ -387,7 +409,6 @@ http_session_receive_request(struct http_session *session, void_star_cb on_eagai
if (old_buffer != session->request_buffer.data) {
http_request->body = header_length ? session->request_buffer.data + header_length : NULL;
}
if (http_session_parse(session, bytes_received) == -1) goto err;
}

@ -1,8 +1,8 @@
#pragma once
#include "http_session.h"
#include "pretty_print.h"
#include "runtime.h"
#include "http_session.h"
extern FILE *http_session_perf_log;
typedef struct http_session http_session;
@ -15,8 +15,8 @@ static inline void
http_session_perf_log_print_header()
{
if (http_session_perf_log == NULL) { perror("http_session perf log"); }
fprintf(http_session_perf_log, "tenant,route,state,header_len,resp_body_len,receive_duration,sent_duration,"
"total_lifetime,preprocessing,proc_MHz\n");
fprintf(http_session_perf_log,
"tenant,route,state,header_len,resp_body_len,receive_duration,sent_duration,total_lifetime,proc_MHz\n");
}
static inline void

@ -2,12 +2,12 @@
#include <errno.h>
#include <inttypes.h>
#include <jsmn.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <jsmn.h>
static inline char *
jsmn_type(jsmntype_t type)

@ -7,6 +7,9 @@
#include "arch/getcycles.h"
#include "runtime.h"
extern uint64_t total_held[1024];
extern uint64_t longest_held[1024];
extern thread_local int thread_id;
/* A linked list of nodes */
struct lock_wrapper {
@ -73,9 +76,13 @@ lock_unlock(lock_t *self, lock_node_t *node)
ck_spinlock_mcs_unlock(&self->lock, &node->node);
uint64_t now = __getcycles();
assert(node->time_locked < now);
assert(node->time_locked <= now);
uint64_t duration = now - node->time_locked;
node->time_locked = 0;
if (unlikely(duration > self->longest_held)) { self->longest_held = duration; }
self->total_held += duration;
if (unlikely(duration > longest_held[thread_id])) {
longest_held[thread_id] = duration;
}
total_held[thread_id] += duration;
}

@ -98,12 +98,12 @@ map_set(struct map *map, uint8_t *key, uint32_t key_len, uint8_t *value, uint32_
}
struct map_node *new_node = (struct map_node *)xmalloc(sizeof(struct map_node));
*(new_node) = (struct map_node){.hash = hash,
.key = xmalloc(key_len),
.key_len = key_len,
.value = xmalloc(value_len),
.value_len = value_len,
.next = bucket->head};
*(new_node) = (struct map_node){ .hash = hash,
.key = xmalloc(key_len),
.key_len = key_len,
.value = xmalloc(value_len),
.value_len = value_len,
.next = bucket->head };
// Copy Key and Value
memcpy(new_node->key, key, key_len);
@ -174,12 +174,12 @@ map_upsert(struct map *map, uint8_t *key, uint32_t key_len, uint8_t *value, uint
struct map_node *new_node = (struct map_node *)xmalloc(sizeof(struct map_node));
*(new_node) = (struct map_node){.hash = hash,
.key = xmalloc(key_len),
.key_len = key_len,
.value = xmalloc(value_len),
.value_len = value_len,
.next = bucket->head};
*(new_node) = (struct map_node){ .hash = hash,
.key = xmalloc(key_len),
.key_len = key_len,
.value = xmalloc(value_len),
.value_len = value_len,
.next = bucket->head };
assert(new_node->key);
assert(new_node->value);

@ -1,11 +1,22 @@
#pragma once
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include "admissions_control.h"
#include "admissions_info.h"
#include "current_wasm_module_instance.h"
#include "panic.h"
#include "pool.h"
#include "sledge_abi_symbols.h"
#include "tcp_server.h"
#include "types.h"
#include "wasm_memory.h"
#include "sledge_abi_symbols.h"
#include "wasm_stack.h"
#include "wasm_memory.h"
#include "wasm_table.h"
extern thread_local int worker_thread_idx;
@ -17,15 +28,9 @@ struct module_pool {
struct wasm_stack_pool stack;
} CACHE_PAD_ALIGNED;
enum module_type
{
APP_MODULE,
PREPROCESS_MODULE
};
struct module {
char *path;
uint32_t stack_size; /* a specification? */
enum module_type type;
char *path;
uint32_t stack_size; /* a specification? */
/* Handle and ABI Symbols for *.so file */
struct sledge_abi_symbols abi;
@ -36,13 +41,12 @@ struct module {
struct module_pool *pools;
} CACHE_PAD_ALIGNED;
/********************************
* Public Methods from module.c *
*******************************/
void module_free(struct module *module);
struct module *module_alloc(char *path, enum module_type type);
struct module *module_alloc(char *path);
/*************************
* Public Static Inlines *
@ -111,9 +115,7 @@ module_alloc_table(struct module *module)
static inline void
module_initialize_pools(struct module *module)
{
/* Create only a single pool for the preprocessing module, since it is executed only by the event core. */
const int n = module->type == APP_MODULE ? runtime_worker_threads_count : 1;
for (int i = 0; i < n; i++) {
for (int i = 0; i < runtime_worker_threads_count; i++) {
wasm_memory_pool_init(&module->pools[i].memory, false);
wasm_stack_pool_init(&module->pools[i].stack, false);
}
@ -122,8 +124,7 @@ module_initialize_pools(struct module *module)
static inline void
module_deinitialize_pools(struct module *module)
{
const int n = module->type == APP_MODULE ? runtime_worker_threads_count : 1;
for (int i = 0; i < n; i++) {
for (int i = 0; i < runtime_worker_threads_count; i++) {
wasm_memory_pool_deinit(&module->pools[i].memory);
wasm_stack_pool_deinit(&module->pools[i].stack);
}

@ -72,8 +72,8 @@ perf_window_fill(struct perf_window *perf_window, uint64_t newest_execution_time
{
for (uint16_t i = 0; i < PERF_WINDOW_CAPACITY; i++) {
perf_window->by_termination[i] = i;
perf_window->by_duration[i] = (struct execution_node){.execution_time = newest_execution_time,
.by_termination_idx = i};
perf_window->by_duration[i] = (struct execution_node){ .execution_time = newest_execution_time,
.by_termination_idx = i };
}
perf_window->count = PERF_WINDOW_CAPACITY;
}

@ -1,7 +1,7 @@
#pragma once
#include <stdarg.h>
#include <stdio.h>
#include <stdarg.h>
#define PRETTY_PRINT_COLOR_CODE_RED "\033[1;31m"
#define PRETTY_COLOR_CODE_GREEN "\033[0;32m"

@ -3,8 +3,8 @@
#include <errno.h>
#include "listener_thread.h"
#include "lock.h"
#include "listener_thread.h"
#include "panic.h"
#include "runtime.h"
#include "worker_thread.h"

@ -2,8 +2,8 @@
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "runtime.h" /* For runtime_pid */

@ -1,32 +1,22 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <stddef.h>
#include "execution_histogram.h"
#include "http_route_total.h"
#include "admissions_info.h"
#include "module.h"
#include "http_route_total.h"
#include "perf_window.h"
struct regression_model {
double bias;
double scale;
uint32_t num_of_param;
double beta1;
double beta2;
};
/* Assumption: entrypoint is always _start. This should be enhanced later */
struct route {
char *route;
struct http_route_total metrics;
struct module *module;
/* HTTP State */
uint32_t relative_deadline_us;
uint64_t relative_deadline; /* cycles */
char *response_content_type;
struct execution_histogram execution_histogram;
struct perf_window latency;
struct module *module_proprocess;
struct regression_model regr_model;
uint32_t relative_deadline_us;
uint64_t relative_deadline; /* cycles */
char *response_content_type;
struct admissions_info admissions_info;
struct perf_window latency;
};

@ -13,13 +13,8 @@ enum route_config_member
route_config_member_route,
route_config_member_path,
route_config_member_admissions_percentile,
route_config_member_expected_execution_us,
route_config_member_relative_deadline_us,
route_config_member_path_preprocess,
route_config_member_model_bias,
route_config_member_model_scale,
route_config_member_model_num_of_param,
route_config_member_model_beta1,
route_config_member_model_beta2,
route_config_member_http_resp_content_type,
route_config_member_len
};
@ -28,13 +23,8 @@ struct route_config {
char *route;
char *path;
uint8_t admissions_percentile;
uint32_t expected_execution_us;
uint32_t relative_deadline_us;
char *path_preprocess;
uint32_t model_bias;
uint32_t model_scale;
uint32_t model_num_of_param;
uint32_t model_beta1;
uint32_t model_beta2;
char *http_resp_content_type;
};
@ -55,15 +45,9 @@ route_config_print(struct route_config *config)
printf("[Route] Route: %s\n", config->route);
printf("[Route] Path: %s\n", config->path);
printf("[Route] Admissions Percentile: %hhu\n", config->admissions_percentile);
printf("[Route] Expected Execution (us): %u\n", config->expected_execution_us);
printf("[Route] Relative Deadline (us): %u\n", config->relative_deadline_us);
printf("[Route] HTTP Response Content Type: %s\n", config->http_resp_content_type);
#ifdef EXECUTION_HISTOGRAM
printf("[Route] Path of Preprocessing Module: %s\n", config->path_preprocess);
printf("[Route] Model Bias: %u\n", config->model_bias);
printf("[Route] Model Scale: %u\n", config->model_scale);
printf("[Route] Model Num of Parameters: %u\n", config->model_num_of_param);
printf("[Route] Model Betas: [%u, %u]\n", config->model_beta1, config->model_beta2);
#endif
}
/**
@ -75,7 +59,7 @@ static inline int
route_config_validate(struct route_config *config, bool *did_set)
{
if (did_set[route_config_member_route] == false) {
fprintf(stderr, "route field is required\n");
fprintf(stderr, "path field is required\n");
return -1;
}
@ -89,9 +73,9 @@ route_config_validate(struct route_config *config, bool *did_set)
config->http_resp_content_type = "text/plain";
}
if (scheduler != SCHEDULER_FIFO && scheduler != SCHEDULER_SJF) {
if (scheduler != SCHEDULER_FIFO) {
if (did_set[route_config_member_relative_deadline_us] == false) {
fprintf(stderr, "relative_deadline_us is required for the selected scheduler\n");
fprintf(stderr, "relative_deadline_us is required\n");
return -1;
}
@ -100,80 +84,36 @@ route_config_validate(struct route_config *config, bool *did_set)
(uint32_t)RUNTIME_RELATIVE_DEADLINE_US_MAX, config->relative_deadline_us);
return -1;
}
}
#ifdef EXECUTION_HISTOGRAM
if (config->admissions_percentile > 99 || config->admissions_percentile < 50) {
fprintf(stderr, "admissions-percentile must be > 50 and <= 99 but was %u, defaulting to 70\n",
config->admissions_percentile);
config->admissions_percentile = 70;
}
#endif
#ifdef EXECUTION_REGRESSION
if (did_set[route_config_member_path_preprocess] == false) {
fprintf(stderr, "model path_preprocess field is required. Put zero if just default preprocessing\n");
return -1;
} else if (strcmp(config->path_preprocess, "0") == 0) {
config->path_preprocess = NULL;
}
if (did_set[route_config_member_model_bias] == false) {
fprintf(stderr, "model bias field is required\n");
return -1;
}
if (did_set[route_config_member_model_scale] == false) {
fprintf(stderr, "model scale field is required\n");
return -1;
}
if (config->model_scale == 0) {
fprintf(stderr, "model scale cannot be zero (to avoid divide by zero)\n");
return -1;
}
if (did_set[route_config_member_model_num_of_param] == false) {
fprintf(stderr, "model num_of_param field is required\n");
return -1;
}
if (did_set[route_config_member_model_beta1] == false) {
fprintf(stderr, "model beta1 field is required\n");
return -1;
}
if (config->model_beta1 == 0) {
fprintf(stderr, "model beta1 cannot be zero (to avoid divide by zero)\n");
return -1;
}
if (did_set[route_config_member_model_beta2] == false) {
fprintf(stderr, "model beta2 field is required. Put zero for just default preprocessing\n");
return -1;
}
#ifdef ADMISSIONS_CONTROL
if (did_set[route_config_member_expected_execution_us] == false) {
fprintf(stderr, "expected-execution-us is required\n");
return -1;
}
if (config->model_num_of_param < 1) {
fprintf(stderr, "model num_of_param must be at least 1 (just default preprocessing)\n");
return -1;
} else if (config->model_num_of_param == 1) {
if (config->path_preprocess) {
fprintf(stderr, "model_num_of_param cannot be 1 when using tenant preprocessing\n");
if (did_set[route_config_member_admissions_percentile] == false) {
fprintf(stderr, "admissions_percentile is required\n");
return -1;
}
config->model_beta2 = 1; /* This is to avoid divide-by-zero */
} else {
/* For now we just support up to two params */
assert(config->model_num_of_param == 2);
if (config->path_preprocess == NULL) {
fprintf(stderr, "model_num_of_param cannot be more than 1 when just default preprocessing\n");
if (config->admissions_percentile > 99 || config->admissions_percentile < 50) {
fprintf(stderr, "admissions-percentile must be > 50 and <= 99 but was %u\n",
config->admissions_percentile);
return -1;
}
if (config->model_beta2 == 0) {
fprintf(stderr, "model beta2 cannot be zero (to avoid divide by zero)\n");
/* If the ratio is too big, admissions control is too coarse */
uint32_t ratio = config->relative_deadline_us / config->expected_execution_us;
if (ratio > ADMISSIONS_CONTROL_GRANULARITY) {
fprintf(stderr,
"Ratio of Deadline to Execution time cannot exceed admissions control "
"granularity of "
"%d\n",
ADMISSIONS_CONTROL_GRANULARITY);
return -1;
}
}
#endif
}
return 0;
}

@ -6,10 +6,12 @@
#include "json.h"
#include "route_config.h"
static const char *route_config_json_keys[route_config_member_len] =
{"route", "path", "admissions-percentile", "relative-deadline-us",
"path_preprocess", "model-bias", "model-scale", "model-num-of-param",
"model-beta1", "model-beta2", "http-resp-content-type"};
static const char *route_config_json_keys[route_config_member_len] = { "route",
"path",
"admissions-percentile",
"expected-execution-us",
"relative-deadline-us",
"http-resp-content-type" };
static inline int
route_config_set_key_once(bool *did_set, enum route_config_member member)
@ -28,8 +30,8 @@ route_config_parse(struct route_config *config, const char *json_buf, jsmntok_t
int tokens_size)
{
int i = tokens_base;
char key[32] = {0};
bool did_set[route_config_member_len] = {false};
char key[32] = { 0 };
bool did_set[route_config_member_len] = { false };
if (!has_valid_type(tokens[i], "Anonymous Route Config Object", JSMN_OBJECT, json_buf)) return -1;
if (!is_nonempty_object(tokens[i], "Anonymous Route Config Object")) return -1;
@ -59,11 +61,6 @@ route_config_parse(struct route_config *config, const char *json_buf, jsmntok_t
if (route_config_set_key_once(did_set, route_config_member_path) == -1) return -1;
config->path = strndup(json_buf + tokens[i].start, tokens[i].end - tokens[i].start);
} else if (strcmp(key, route_config_json_keys[route_config_member_path_preprocess]) == 0) {
if (!is_nonempty_string(tokens[i], key)) return -1;
if (route_config_set_key_once(did_set, route_config_member_path_preprocess) == -1) return -1;
config->path_preprocess = strndup(json_buf + tokens[i].start, tokens[i].end - tokens[i].start);
} else if (strcmp(key, route_config_json_keys[route_config_member_admissions_percentile]) == 0) {
if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1;
if (route_config_set_key_once(did_set, route_config_member_admissions_percentile) == -1)
@ -73,57 +70,23 @@ route_config_parse(struct route_config *config, const char *json_buf, jsmntok_t
route_config_json_keys[route_config_member_admissions_percentile],
&config->admissions_percentile);
if (rc < 0) return -1;
} else if (strcmp(key, route_config_json_keys[route_config_member_relative_deadline_us]) == 0) {
} else if (strcmp(key, route_config_json_keys[route_config_member_expected_execution_us]) == 0) {
if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1;
if (route_config_set_key_once(did_set, route_config_member_relative_deadline_us) == -1)
if (route_config_set_key_once(did_set, route_config_member_expected_execution_us) == -1)
return -1;
int rc = parse_uint32_t(tokens[i], json_buf,
route_config_json_keys[route_config_member_relative_deadline_us],
&config->relative_deadline_us);
if (rc < 0) return -1;
} else if (strcmp(key, "expected-execution-us") == 0) {
if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1;
printf("The \"expected-execution-us\" field has been deprecated, so no need.\n");
} else if (strcmp(key, route_config_json_keys[route_config_member_model_bias]) == 0) {
if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1;
if (route_config_set_key_once(did_set, route_config_member_model_bias) == -1) return -1;
int rc = parse_uint32_t(tokens[i], json_buf,
route_config_json_keys[route_config_member_model_bias],
&config->model_bias);
if (rc < 0) return -1;
} else if (strcmp(key, route_config_json_keys[route_config_member_model_scale]) == 0) {
if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1;
if (route_config_set_key_once(did_set, route_config_member_model_scale) == -1) return -1;
int rc = parse_uint32_t(tokens[i], json_buf,
route_config_json_keys[route_config_member_model_scale],
&config->model_scale);
if (rc < 0) return -1;
} else if (strcmp(key, route_config_json_keys[route_config_member_model_num_of_param]) == 0) {
if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1;
if (route_config_set_key_once(did_set, route_config_member_model_num_of_param) == -1) return -1;
int rc = parse_uint32_t(tokens[i], json_buf,
route_config_json_keys[route_config_member_model_num_of_param],
&config->model_num_of_param);
if (rc < 0) return -1;
} else if (strcmp(key, route_config_json_keys[route_config_member_model_beta1]) == 0) {
if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1;
if (route_config_set_key_once(did_set, route_config_member_model_beta1) == -1) return -1;
int rc = parse_uint32_t(tokens[i], json_buf,
route_config_json_keys[route_config_member_model_beta1],
&config->model_beta1);
route_config_json_keys[route_config_member_expected_execution_us],
&config->expected_execution_us);
if (rc < 0) return -1;
} else if (strcmp(key, route_config_json_keys[route_config_member_model_beta2]) == 0) {
} else if (strcmp(key, route_config_json_keys[route_config_member_relative_deadline_us]) == 0) {
if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1;
if (route_config_set_key_once(did_set, route_config_member_model_beta2) == -1) return -1;
if (route_config_set_key_once(did_set, route_config_member_relative_deadline_us) == -1)
return -1;
int rc = parse_uint32_t(tokens[i], json_buf,
route_config_json_keys[route_config_member_model_beta2],
&config->model_beta2);
route_config_json_keys[route_config_member_relative_deadline_us],
&config->relative_deadline_us);
if (rc < 0) return -1;
} else if (strcmp(key, route_config_json_keys[route_config_member_http_resp_content_type]) == 0) {
if (!is_nonempty_string(tokens[i], key)) return -1;

@ -1,10 +1,10 @@
#pragma once
#include <pthread.h>
#include <stdatomic.h>
#include <stdbool.h>
#include <sys/epoll.h> /* for epoll_create1(), epoll_ctl(), struct epoll_event */
#include <sys/types.h> /* for pid_t */
#include <stdatomic.h>
#include <stdbool.h>
#include "likely.h"
#include "types.h"

@ -1,12 +1,12 @@
#pragma once
#include <sys/mman.h>
#include <stddef.h>
#include <stdint.h>
#include <sys/mman.h>
#include "panic.h"
#include "sandbox_types.h"
#include "tenant.h"
#include "sandbox_types.h"
/***************************
* Public API *

@ -13,10 +13,9 @@ static inline void
sandbox_perf_log_print_header()
{
if (sandbox_perf_log == NULL) { perror("sandbox perf log"); }
fprintf(sandbox_perf_log,
"id,tenant,route,state,deadline,actual,queued,uninitialized,allocated,initialized,"
"runnable,interrupted,preempted,"
"running_sys,running_user,asleep,returned,complete,error,proc_MHz,payload_size,regression_param\n");
fprintf(sandbox_perf_log, "id,tenant,route,state,deadline,actual,queued,uninitialized,allocated,initialized,"
"runnable,interrupted,preempted,"
"running_sys,running_user,asleep,returned,complete,error,proc_MHz,memory\n");
}
/**
@ -37,8 +36,7 @@ sandbox_perf_log_print_entry(struct sandbox *sandbox)
* becomes more intelligent, then peak linear memory size needs to be tracked
* seperately from current linear memory size.
*/
fprintf(sandbox_perf_log,
"%lu,%s,%s,%s,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%u,%u,%d,%d,%lf\n",
fprintf(sandbox_perf_log, "%lu,%s,%s,%s,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%u\n",
sandbox->id, sandbox->tenant->name, sandbox->route->route, sandbox_state_stringify(sandbox->state),
sandbox->route->relative_deadline, sandbox->total_time, queued_duration,
sandbox->duration_of_state[SANDBOX_UNINITIALIZED], sandbox->duration_of_state[SANDBOX_ALLOCATED],
@ -47,10 +45,10 @@ sandbox_perf_log_print_entry(struct sandbox *sandbox)
sandbox->duration_of_state[SANDBOX_RUNNING_SYS], sandbox->duration_of_state[SANDBOX_RUNNING_USER],
sandbox->duration_of_state[SANDBOX_ASLEEP], sandbox->duration_of_state[SANDBOX_RETURNED],
sandbox->duration_of_state[SANDBOX_COMPLETE], sandbox->duration_of_state[SANDBOX_ERROR],
runtime_processor_speed_MHz, sandbox->response_code, 0, sandbox->payload_size,
sandbox->regression_param);
runtime_processor_speed_MHz);
}
static inline void
sandbox_perf_log_init()
{

@ -5,10 +5,10 @@
#include "arch/getcycles.h"
#include "local_runqueue.h"
#include "sandbox_types.h"
#include "sandbox_state.h"
#include "sandbox_state_history.h"
#include "sandbox_state_transition.h"
#include "sandbox_types.h"
/**
* Transitions a sandbox to the SANDBOX_ASLEEP state.

@ -3,9 +3,7 @@
#include <assert.h>
#include <stdint.h>
#include "admissions_control.h"
#include "arch/getcycles.h"
#include "execution_histogram.h"
#include "panic.h"
#include "sandbox_functions.h"
#include "sandbox_perf_log.h"
@ -48,24 +46,15 @@ sandbox_set_as_complete(struct sandbox *sandbox, sandbox_state_t last_state)
sandbox_state_totals_increment(SANDBOX_COMPLETE);
sandbox_state_totals_decrement(last_state);
struct route *route = sandbox->route;
#ifdef EXECUTION_HISTOGRAM
/* Execution Histogram Post Processing */
const uint64_t execution_duration = sandbox->duration_of_state[SANDBOX_RUNNING_USER]
+ sandbox->duration_of_state[SANDBOX_RUNNING_SYS];
execution_histogram_update(&route->execution_histogram, execution_duration);
#endif
#ifdef ADMISSIONS_CONTROL
/* Admissions Control Post Processing */
admissions_info_update(&sandbox->route->admissions_info, sandbox->duration_of_state[SANDBOX_RUNNING_USER]
+ sandbox->duration_of_state[SANDBOX_RUNNING_SYS]);
admissions_control_subtract(sandbox->admissions_estimate);
#endif
/* Terminal State Logging for Sandbox */
sandbox_perf_log_print_entry(sandbox);
sandbox_summarize_page_allocations(sandbox);
route_latency_add(&route->latency, sandbox->total_time);
route_latency_add(&sandbox->route->latency, sandbox->total_time);
/* State Change Hooks */
sandbox_state_transition_from_hook(sandbox, last_state);

@ -3,17 +3,16 @@
#include <assert.h>
#include <stdint.h>
#include "admissions_control.h"
#include "arch/getcycles.h"
#include "listener_thread.h"
#include "local_runqueue.h"
#include "panic.h"
#include "sandbox_state.h"
#include "sandbox_functions.h"
#include "sandbox_perf_log.h"
#include "sandbox_state.h"
#include "sandbox_state_history.h"
#include "sandbox_state_transition.h"
#include "sandbox_summarize_page_allocations.h"
#include "panic.h"
/**
* Transitions a sandbox to the SANDBOX_ERROR state.
@ -49,26 +48,19 @@ sandbox_set_as_error(struct sandbox *sandbox, sandbox_state_t last_state)
/* State Change Bookkeeping */
assert(now > sandbox->timestamp_of.last_state_change);
sandbox->last_state_duration = now - sandbox->timestamp_of.last_state_change;
if (last_state == SANDBOX_RUNNING_SYS) {
sandbox->remaining_exec = (sandbox->remaining_exec > sandbox->last_state_duration)
? sandbox->remaining_exec - sandbox->last_state_duration
: 0;
}
sandbox->duration_of_state[last_state] += sandbox->last_state_duration;
sandbox->timestamp_of.last_state_change = now;
sandbox_state_history_append(&sandbox->state_history, SANDBOX_ERROR);
sandbox_state_totals_increment(SANDBOX_ERROR);
sandbox_state_totals_decrement(last_state);
#ifdef ADMISSIONS_CONTROL
/* Admissions Control Post Processing */
admissions_control_subtract(sandbox->admissions_estimate);
#endif
/* Return HTTP session to listener core to be written back to client */
http_session_set_response_header(sandbox->http, 500);
sandbox->http->state = HTTP_SESSION_EXECUTION_COMPLETE;
http_session_send_response(sandbox->http, (void_star_cb)listener_thread_register_http_session);
//http_session_send_response(sandbox->http, (void_star_cb)listener_thread_register_http_session);
sandbox->http = NULL;
/* Terminal State Logging */

@ -34,7 +34,7 @@ sandbox_set_as_initialized(struct sandbox *sandbox, sandbox_state_t last_state)
}
/* State Change Bookkeeping */
assert(now > sandbox->timestamp_of.last_state_change);
assert(now >= sandbox->timestamp_of.last_state_change);
sandbox->last_state_duration = now - sandbox->timestamp_of.last_state_change;
sandbox->duration_of_state[last_state] += sandbox->last_state_duration;
sandbox->timestamp_of.last_state_change = now;

@ -25,10 +25,6 @@ sandbox_set_as_interrupted(struct sandbox *sandbox, sandbox_state_t last_state)
/* State Change Bookkeeping */
assert(now > sandbox->timestamp_of.last_state_change);
sandbox->last_state_duration = now - sandbox->timestamp_of.last_state_change;
assert(last_state == SANDBOX_RUNNING_USER);
sandbox->remaining_exec = (sandbox->remaining_exec > sandbox->last_state_duration)
? sandbox->remaining_exec - sandbox->last_state_duration
: 0;
sandbox->duration_of_state[last_state] += sandbox->last_state_duration;
sandbox->timestamp_of.last_state_change = now;
/* We do not append SANDBOX_INTERRUPTED to the sandbox_state_history because it would quickly fill the buffer */

@ -3,8 +3,8 @@
#include <assert.h>
#include <stdint.h>
#include "arch/getcycles.h"
#include "auto_buf.h"
#include "arch/getcycles.h"
#include "listener_thread.h"
#include "local_runqueue.h"
#include "panic.h"
@ -43,27 +43,22 @@ sandbox_set_as_returned(struct sandbox *sandbox, sandbox_state_t last_state)
}
/* State Change Bookkeeping */
assert(now > sandbox->timestamp_of.last_state_change);
assert(now >= sandbox->timestamp_of.last_state_change);
sandbox->last_state_duration = now - sandbox->timestamp_of.last_state_change;
sandbox->remaining_exec = (sandbox->remaining_exec > sandbox->last_state_duration)
? sandbox->remaining_exec - sandbox->last_state_duration
: 0;
sandbox->duration_of_state[last_state] += sandbox->last_state_duration;
sandbox->timestamp_of.last_state_change = now;
sandbox_state_history_append(&sandbox->state_history, SANDBOX_RETURNED);
sandbox_state_totals_increment(SANDBOX_RETURNED);
sandbox_state_totals_decrement(last_state);
http_session_set_response_header(sandbox->http, 200);
//http_session_set_response_header(sandbox->http, 200);
sandbox->http->state = HTTP_SESSION_EXECUTION_COMPLETE;
http_session_send_response(sandbox->http, (void_star_cb)listener_thread_register_http_session);
//http_session_send_response(sandbox->http, (void_star_cb)listener_thread_register_http_session);
sandbox->http = NULL;
/* State Change Hooks */
sandbox_state_transition_from_hook(sandbox, last_state);
sandbox_state_transition_to_hook(sandbox, SANDBOX_RETURNED);
assert(sandbox->response_code == 0);
sandbox->response_code = 200;
sandbox_process_scheduler_updates(sandbox);
}

@ -39,13 +39,8 @@ sandbox_set_as_running_sys(struct sandbox *sandbox, sandbox_state_t last_state)
}
/* State Change Bookkeeping */
assert(now > sandbox->timestamp_of.last_state_change);
assert(now >= sandbox->timestamp_of.last_state_change);
sandbox->last_state_duration = now - sandbox->timestamp_of.last_state_change;
if (last_state == SANDBOX_RUNNING_USER) {
sandbox->remaining_exec = (sandbox->remaining_exec > sandbox->last_state_duration)
? sandbox->remaining_exec - sandbox->last_state_duration
: 0;
}
sandbox->duration_of_state[last_state] += sandbox->last_state_duration;
sandbox->timestamp_of.last_state_change = now;
sandbox_state_history_append(&sandbox->state_history, SANDBOX_RUNNING_SYS);
@ -60,8 +55,6 @@ sandbox_set_as_running_sys(struct sandbox *sandbox, sandbox_state_t last_state)
static inline void
sandbox_syscall(struct sandbox *sandbox)
{
if (sandbox->module->type == PREPROCESS_MODULE) return;
assert(sandbox->state == SANDBOX_RUNNING_USER);
sandbox_set_as_running_sys(sandbox, SANDBOX_RUNNING_USER);

@ -6,10 +6,10 @@
#include "arch/getcycles.h"
#include "current_sandbox.h"
#include "panic.h"
#include "sandbox_functions.h"
#include "sandbox_state_history.h"
#include "sandbox_state_transition.h"
#include "sandbox_types.h"
#include "sandbox_functions.h"
static inline void
sandbox_set_as_running_user(struct sandbox *sandbox, sandbox_state_t last_state)
@ -35,13 +35,8 @@ sandbox_set_as_running_user(struct sandbox *sandbox, sandbox_state_t last_state)
/* State Change Bookkeeping */
assert(now > sandbox->timestamp_of.last_state_change);
assert(now >= sandbox->timestamp_of.last_state_change);
sandbox->last_state_duration = now - sandbox->timestamp_of.last_state_change;
if (last_state == SANDBOX_RUNNING_SYS) {
sandbox->remaining_exec = (sandbox->remaining_exec > sandbox->last_state_duration)
? sandbox->remaining_exec - sandbox->last_state_duration
: 0;
}
sandbox->duration_of_state[last_state] += sandbox->last_state_duration;
sandbox->timestamp_of.last_state_change = now;
sandbox_state_history_append(&sandbox->state_history, SANDBOX_RUNNING_USER);
@ -66,8 +61,6 @@ sandbox_set_as_running_user(struct sandbox *sandbox, sandbox_state_t last_state)
static inline void
sandbox_return(struct sandbox *sandbox)
{
if (sandbox->module->type == PREPROCESS_MODULE) return;
assert(sandbox->state == SANDBOX_RUNNING_SYS);
sandbox_set_as_running_user(sandbox, SANDBOX_RUNNING_SYS);
}

@ -9,11 +9,11 @@
#include "sandbox_state.h"
#include "sandbox_state_history.h"
#include "tenant.h"
#include "wasi.h"
#include "wasm_globals.h"
#include "wasm_memory.h"
#include "wasm_stack.h"
#include "wasm_types.h"
#include "wasm_stack.h"
#include "wasm_globals.h"
#include "wasi.h"
/*********************
* Structs and Types *
@ -38,7 +38,6 @@ struct sandbox {
uint64_t id;
sandbox_state_t state;
struct sandbox_state_history state_history;
uint16_t response_code;
/* Accounting Info */
@ -47,6 +46,8 @@ struct sandbox {
/* HTTP State */
struct http_session *http;
struct auto_buf response_body;
struct auto_buf response_header;
/* WebAssembly Module State */
struct module *module; /* the module this is an instance of */
@ -62,13 +63,12 @@ struct sandbox {
uint64_t duration_of_state[SANDBOX_STATE_COUNT];
uint64_t last_state_duration;
uint64_t remaining_exec;
uint64_t absolute_deadline;
uint64_t admissions_estimate; /* estimated execution time (cycles) * runtime_admissions_granularity / relative
deadline (cycles) */
uint64_t total_time; /* Total time from Request to Response */
int payload_size;
double regression_param; /* Calculated in tenant preprocessing logic if provided */
int cursor;
/* System Interface State */
int32_t return_value;

@ -9,21 +9,22 @@
#include "global_request_scheduler_deque.h"
#include "global_request_scheduler_minheap.h"
#include "global_request_scheduler_mtds.h"
#include "local_cleanup_queue.h"
#include "local_runqueue.h"
#include "local_runqueue_list.h"
#include "local_runqueue_minheap.h"
#include "local_runqueue_list.h"
#include "local_cleanup_queue.h"
#include "local_runqueue_mtds.h"
#include "panic.h"
#include "sandbox_functions.h"
#include "sandbox_set_as_interrupted.h"
#include "sandbox_types.h"
#include "sandbox_set_as_preempted.h"
#include "sandbox_set_as_runnable.h"
#include "sandbox_set_as_running_sys.h"
#include "sandbox_set_as_interrupted.h"
#include "sandbox_set_as_running_user.h"
#include "sandbox_types.h"
#include "scheduler_options.h"
extern thread_local bool pthread_stop;
/**
* This scheduler provides for cooperative and preemptive multitasking in a OS process's userspace.
@ -106,31 +107,6 @@ done:
return local_runqueue_get_next();
}
static inline struct sandbox *
scheduler_sjf_get_next()
{
struct sandbox *local = local_runqueue_get_next();
uint64_t local_rem_exec = local == NULL ? UINT64_MAX : local->remaining_exec;
struct sandbox *global = NULL;
uint64_t global_remaining_exec = global_request_scheduler_peek();
/* Try to pull and allocate from the global queue if earlier
* This will be placed at the head of the local runqueue */
if (global_remaining_exec < local_rem_exec) {
if (global_request_scheduler_remove_if_earlier(&global, local_rem_exec) == 0) {
assert(global != NULL);
assert(global->remaining_exec < local_rem_exec);
sandbox_prepare_execution_environment(global);
assert(global->state == SANDBOX_INITIALIZED);
sandbox_set_as_runnable(global, SANDBOX_INITIALIZED);
}
}
/* Return what is at the head of the local runqueue or NULL if empty */
return local_runqueue_get_next();
}
static inline struct sandbox *
scheduler_edf_get_next()
{
@ -188,8 +164,6 @@ scheduler_get_next()
return scheduler_mtdbf_get_next();
case SCHEDULER_MTDS:
return scheduler_mtds_get_next();
case SCHEDULER_SJF:
return scheduler_sjf_get_next();
case SCHEDULER_EDF:
return scheduler_edf_get_next();
case SCHEDULER_FIFO:
@ -204,13 +178,12 @@ scheduler_initialize()
{
switch (scheduler) {
case SCHEDULER_MTDBF:
/* TODO: loading */
// global_request_scheduler_mtdbf_initialize();
break;
case SCHEDULER_MTDS:
global_request_scheduler_mtds_initialize();
break;
case SCHEDULER_EDF:
case SCHEDULER_SJF:
global_request_scheduler_minheap_initialize();
break;
case SCHEDULER_FIFO:
@ -232,7 +205,6 @@ scheduler_runqueue_initialize()
local_runqueue_mtds_initialize();
break;
case SCHEDULER_EDF:
case SCHEDULER_SJF:
local_runqueue_minheap_initialize();
break;
case SCHEDULER_FIFO:
@ -251,8 +223,6 @@ scheduler_print(enum SCHEDULER variant)
return "FIFO";
case SCHEDULER_EDF:
return "EDF";
case SCHEDULER_SJF:
return "SJF";
case SCHEDULER_MTDS:
return "MTDS";
case SCHEDULER_MTDBF:
@ -318,7 +288,6 @@ scheduler_process_policy_specific_updates_on_interrupts(struct sandbox *interrup
case SCHEDULER_FIFO:
return;
case SCHEDULER_EDF:
case SCHEDULER_SJF:
return;
case SCHEDULER_MTDS:
local_timeout_queue_process_promotions();
@ -424,7 +393,7 @@ scheduler_switch_to_base_context(struct arch_context *current_context)
static inline void
scheduler_idle_loop()
{
while (true) {
while (!pthread_stop) {
/* Assumption: only called by the "base context" */
assert(current_sandbox_get() == NULL);

@ -2,11 +2,10 @@
enum SCHEDULER
{
SCHEDULER_FIFO,
SCHEDULER_EDF,
SCHEDULER_SJF,
SCHEDULER_MTDS,
SCHEDULER_MTDBF
SCHEDULER_FIFO = 0,
SCHEDULER_EDF = 1,
SCHEDULER_MTDS = 2,
SCHEDULER_MTDBF = 3
};
extern enum SCHEDULER scheduler;

@ -5,8 +5,8 @@
#include <stdint.h>
#include "debuglog.h"
#include "sledge_abi.h"
#include "wasm_types.h"
#include "sledge_abi.h"
struct sledge_abi_symbols {
void *handle;

@ -31,7 +31,7 @@ software_interrupt_mask_signal(int signal)
sigset_t set;
int return_code;
assert(signal == SIGALRM || signal == SIGUSR1 || signal == SIGFPE || signal == SIGSEGV);
assert(signal == SIGALRM || signal == SIGUSR1 || signal == SIGFPE || signal == SIGSEGV || signal == SIGINT);
/* all threads created by the calling thread will have signal blocked */
sigemptyset(&set);
sigaddset(&set, signal);
@ -55,7 +55,7 @@ software_interrupt_unmask_signal(int signal)
sigset_t set;
int return_code;
assert(signal == SIGALRM || signal == SIGUSR1 || signal == SIGFPE || signal == SIGSEGV);
assert(signal == SIGALRM || signal == SIGUSR1 || signal == SIGFPE || signal == SIGSEGV || signal == SIGINT);
/* all threads created by the calling thread will have signal unblocked */
sigemptyset(&set);
sigaddset(&set, signal);

@ -1,7 +1,7 @@
#pragma once
#include <signal.h>
#include <stdatomic.h>
#include <signal.h>
#include <stdlib.h>
#include "worker_thread.h"

@ -3,10 +3,10 @@
#include <assert.h>
#include <errno.h>
#include <netdb.h>
#include <stdint.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include "debuglog.h"

@ -1,7 +1,7 @@
#pragma once
#include <arpa/inet.h>
#include <assert.h>
#include <arpa/inet.h>
#include <errno.h>
#include <stdbool.h>
#include <string.h>
@ -9,8 +9,8 @@
#include <unistd.h>
#include "debuglog.h"
#include "likely.h"
#include "panic.h"
#include "likely.h"
static inline void
tcp_session_close(int client_socket, struct sockaddr *client_address)
@ -21,7 +21,7 @@ tcp_session_close(int client_socket, struct sockaddr *client_address)
assert(client_socket != STDERR_FILENO);
if (unlikely(close(client_socket) < 0)) {
char client_address_text[INET6_ADDRSTRLEN] = {'\0'};
char client_address_text[INET6_ADDRSTRLEN] = { '\0' };
if (unlikely(inet_ntop(AF_INET, &client_address, client_address_text, INET6_ADDRSTRLEN) == NULL)) {
debuglog("Failed to log client_address: %s", strerror(errno));
}

@ -45,10 +45,8 @@ tenant_config_print(struct tenant_config *config)
{
printf("[Tenant] Name: %s\n", config->name);
printf("[Tenant] Path: %d\n", config->port);
if (scheduler == SCHEDULER_MTDS) {
printf("[Tenant] Replenishment Period (us): %u\n", config->replenishment_period_us);
printf("[Tenant] Max Budget (us): %u\n", config->max_budget_us);
}
printf("[Tenant] Replenishment Period (us): %u\n", config->replenishment_period_us);
printf("[Tenant] Max Budget (us): %u\n", config->max_budget_us);
printf("[Tenant] Routes Size: %zu\n", config->routes_len);
for (int i = 0; i < config->routes_len; i++) { route_config_print(&config->routes[i]); }
}
@ -73,19 +71,19 @@ tenant_config_validate(struct tenant_config *config, bool *did_set)
if (scheduler == SCHEDULER_MTDS) {
if (did_set[tenant_config_member_replenishment_period_us] == false) {
fprintf(stderr, "replenishment-period-us field is missing, so defaulting to 0\n");
config->replenishment_period_us = 0;
fprintf(stderr, "replenishment-period-us field is required\n");
return -1;
}
if (config->replenishment_period_us > (uint32_t)RUNTIME_RELATIVE_DEADLINE_US_MAX) {
fprintf(stderr, "relative-deadline-us must be between 0 and %u, was %u\n",
fprintf(stderr, "Relative-deadline-us must be between 0 and %u, was %u\n",
(uint32_t)RUNTIME_RELATIVE_DEADLINE_US_MAX, config->replenishment_period_us);
return -1;
}
if (did_set[tenant_config_member_max_budget_us] == false) {
fprintf(stderr, "max-budget-us field is missing, so defaulting to 0\n");
config->max_budget_us = 0;
fprintf(stderr, "max-budget-us field is required\n");
return -1;
}
if (config->max_budget_us > (uint32_t)RUNTIME_RELATIVE_DEADLINE_US_MAX) {

@ -9,8 +9,8 @@
#include "route_config_parse.h"
#include "tenant_config.h"
static const char *tenant_config_json_keys[tenant_config_member_len] = {"name", "port", "replenishment-period-us",
"max-budget-us", "routes"};
static const char *tenant_config_json_keys[tenant_config_member_len] = { "name", "port", "replenishment-period-us",
"max-budget-us", "routes" };
static inline int
tenant_config_set_key_once(bool *did_set, enum tenant_config_member member)
@ -29,8 +29,8 @@ tenant_config_parse(struct tenant_config *config, const char *json_buf, jsmntok_
int tokens_size)
{
int i = tokens_base;
char key[32] = {0};
bool did_set[tenant_config_member_len] = {false};
char key[32] = { 0 };
bool did_set[tenant_config_member_len] = { false };
if (!has_valid_type(tokens[i], "Anonymous Tenant Config Object", JSMN_OBJECT, json_buf)) return -1;
if (!is_nonempty_object(tokens[i], "Anonymous Tenant Config Object")) return -1;

@ -3,15 +3,16 @@
#include <stdint.h>
#include <string.h>
#include "admissions_info.h"
#include "http.h"
#include "listener_thread.h"
#include "module_database.h"
#include "panic.h"
#include "priority_queue.h"
#include "sandbox_functions.h"
#include "scheduler_options.h"
#include "tenant.h"
#include "tenant_config.h"
#include "priority_queue.h"
#include "sandbox_functions.h"
int tenant_database_add(struct tenant *tenant);
struct tenant *tenant_database_find_by_name(char *name);
@ -29,7 +30,6 @@ tenant_policy_specific_init(struct tenant *tenant, struct tenant_config *config)
case SCHEDULER_FIFO:
break;
case SCHEDULER_EDF:
case SCHEDULER_SJF:
break;
case SCHEDULER_MTDS:
/* Deferable Server Initialization */
@ -103,7 +103,7 @@ tenant_alloc(struct tenant_config *config)
struct module *module = module_database_find_by_path(&tenant->module_db, config->routes[i].path);
if (module == NULL) {
/* Ownership of path moves here */
module = module_alloc(config->routes[i].path, APP_MODULE);
module = module_alloc(config->routes[i].path);
if (module != NULL) {
module_database_add(&tenant->module_db, module);
config->routes[i].path = NULL;
@ -115,30 +115,8 @@ tenant_alloc(struct tenant_config *config)
assert(module != NULL);
struct module *module_proprocess = NULL;
#ifdef EXECUTION_REGRESSION
if (config->routes[i].path_preprocess) {
module_proprocess = module_database_find_by_path(&tenant->module_db,
config->routes[i].path_preprocess);
if (module_proprocess == NULL) {
/* Ownership of path moves here */
module_proprocess = module_alloc(config->routes[i].path_preprocess, PREPROCESS_MODULE);
if (module_proprocess != NULL) {
module_database_add(&tenant->module_db, module_proprocess);
config->routes[i].path_preprocess = NULL;
}
} else {
free(config->routes[i].path_preprocess);
config->routes[i].path_preprocess = NULL;
}
assert(module_proprocess != NULL);
}
#endif
/* Ownership of config's route and http_resp_content_type move here */
int rc = http_router_add_route(&tenant->router, &config->routes[i], module, module_proprocess);
int rc = http_router_add_route(&tenant->router, &config->routes[i], module);
if (unlikely(rc != 0)) {
panic("Tenant %s defined %lu routes, but router failed to grow beyond %lu\n", tenant->name,
config->routes_len, tenant->router.capacity);
@ -182,6 +160,5 @@ get_next_timeout_of_tenant(uint64_t replenishment_period)
* @param tenant
* @returns 0 on success, -1 on error
*/
int tenant_listen(struct tenant *tenant);
int listener_thread_register_tenant(struct tenant *tenant);
void tenant_preprocess(struct http_session *session);
int tenant_listen(struct tenant *tenant);
int listener_thread_register_tenant(struct tenant *tenant);

@ -85,9 +85,9 @@ wasm_globals_set_i32(struct vec_wasm_global_t *globals, uint32_t idx, int32_t va
wasm_global_t *current = vec_wasm_global_t_get(globals, idx);
if (unlikely(current->type != WASM_GLOBAL_TYPE_UNUSED && current->mut == false)) return -2;
int rc =
vec_wasm_global_t_insert(globals, idx,
(wasm_global_t){.mut = is_mutable, .type = WASM_GLOBAL_TYPE_I32, .value = value});
int rc = vec_wasm_global_t_insert(globals, idx,
(wasm_global_t){
.mut = is_mutable, .type = WASM_GLOBAL_TYPE_I32, .value = value });
return rc;
}
@ -99,8 +99,8 @@ wasm_globals_set_i64(struct vec_wasm_global_t *globals, uint32_t idx, int64_t va
if (unlikely(current->type != WASM_GLOBAL_TYPE_UNUSED && current->mut == false)) return -2;
// Returns -1 if idx > capacity
int rc =
vec_wasm_global_t_insert(globals, idx,
(wasm_global_t){.mut = is_mutable, .type = WASM_GLOBAL_TYPE_I64, .value = value});
int rc = vec_wasm_global_t_insert(globals, idx,
(wasm_global_t){
.mut = is_mutable, .type = WASM_GLOBAL_TYPE_I64, .value = value });
return rc;
}

@ -8,8 +8,8 @@
#include <sys/mman.h>
#include "ps_list.h"
#include "sledge_abi.h"
#include "types.h" /* PAGE_SIZE */
#include "sledge_abi.h"
#include "wasm_types.h"
#define WASM_MEMORY_MAX (uint64_t) UINT32_MAX + 1

@ -1,7 +1,7 @@
#pragma once
#include "sledge_abi.h"
#include "wasm_memory.h"
#include "wasm_table.h"
#include "sledge_abi.h"
/* This structure is the runtime representation of the unique state of a module instance
* Currently this is not spec-compliant, as it only supports a single table and a single memory and it excludes many

@ -2,9 +2,9 @@
#include <stdint.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <string.h>
#include <strings.h>
#include <sys/mman.h>
#include "ps_list.h"
#include "types.h"

@ -109,5 +109,5 @@ wasm_table_set(struct sledge_abi__wasm_table *wasm_table, uint32_t idx, uint32_t
/* TODO: atomic for multiple concurrent invocations? Issue #97 */
if (wasm_table->buffer[idx].type_id == type_id && wasm_table->buffer[idx].func_pointer == pointer) return;
wasm_table->buffer[idx] = (struct sledge_abi__wasm_table_entry){.type_id = type_id, .func_pointer = pointer};
wasm_table->buffer[idx] = (struct sledge_abi__wasm_table_entry){ .type_id = type_id, .func_pointer = pointer };
}

@ -8,8 +8,6 @@
#include "panic.h"
#include "runtime.h"
#ifdef ADMISSIONS_CONTROL
/*
* Unitless estimate of the instantaneous fraction of system capacity required to complete all previously
* admitted work. This is used to calculate free capacity as part of admissions control
@ -21,32 +19,40 @@
* success or failure)
*/
#ifdef ADMISSIONS_CONTROL
_Atomic uint64_t admissions_control_admitted;
uint64_t admissions_control_capacity;
const double admissions_control_overhead = 0.2;
#endif
void
admissions_control_initialize()
{
#ifdef ADMISSIONS_CONTROL
atomic_init(&admissions_control_admitted, 0);
admissions_control_capacity = runtime_worker_threads_count * ADMISSIONS_CONTROL_GRANULARITY
* ((double)1.0 - admissions_control_overhead);
#endif
}
void
admissions_control_add(uint64_t admissions_estimate)
{
#ifdef ADMISSIONS_CONTROL
assert(admissions_estimate > 0);
atomic_fetch_add(&admissions_control_admitted, admissions_estimate);
#ifdef LOG_ADMISSIONS_CONTROL
debuglog("Runtime Admitted: %lu / %lu\n", admissions_control_admitted, admissions_control_capacity);
#endif
#endif /* ADMISSIONS_CONTROL */
}
void
admissions_control_subtract(uint64_t admissions_estimate)
{
#ifdef ADMISSIONS_CONTROL
/* Assumption: Should never underflow */
if (unlikely(admissions_estimate > admissions_control_admitted)) panic("Admissions Estimate underflow\n");
@ -55,11 +61,14 @@ admissions_control_subtract(uint64_t admissions_estimate)
#ifdef LOG_ADMISSIONS_CONTROL
debuglog("Runtime Admitted: %lu / %lu\n", admissions_control_admitted, admissions_control_capacity);
#endif
#endif /* ADMISSIONS_CONTROL */
}
uint64_t
admissions_control_calculate_estimate(uint64_t estimated_execution, uint64_t relative_deadline)
{
#ifdef ADMISSIONS_CONTROL
assert(relative_deadline != 0);
uint64_t admissions_estimate = (estimated_execution * (uint64_t)ADMISSIONS_CONTROL_GRANULARITY)
/ relative_deadline;
@ -67,15 +76,31 @@ admissions_control_calculate_estimate(uint64_t estimated_execution, uint64_t rel
panic("Ratio of Deadline to Execution time cannot exceed %d\n", ADMISSIONS_CONTROL_GRANULARITY);
return admissions_estimate;
#else
return 0;
#endif
}
uint64_t
admissions_control_calculate_estimate_us(uint32_t estimated_execution_us, uint32_t relative_deadline_us)
{
#ifdef ADMISSIONS_CONTROL
assert(relative_deadline_us != 0);
return (uint64_t)((uint64_t)(estimated_execution_us * ADMISSIONS_CONTROL_GRANULARITY)) / relative_deadline_us;
#else
return 0;
#endif
}
void
admissions_control_log_decision(uint64_t admissions_estimate, bool admitted)
{
#ifdef ADMISSIONS_CONTROL
#ifdef LOG_ADMISSIONS_CONTROL
debuglog("Admitted: %lu, Capacity: %lu, Estimate: %lu, Admitted? %s\n", admissions_control_admitted,
admissions_control_capacity, admissions_estimate, admitted ? "yes" : "no");
#endif /* LOG_ADMISSIONS_CONTROL */
#endif /* ADMISSIONS_CONTROL */
}
uint64_t
@ -83,6 +108,7 @@ admissions_control_decide(uint64_t admissions_estimate)
{
uint64_t work_admitted = 1; /* Nominal non-zero value in case admissions control is disabled */
#ifdef ADMISSIONS_CONTROL
if (unlikely(admissions_estimate == 0)) panic("Admissions estimate should never be zero");
uint64_t total_admitted = atomic_load(&admissions_control_admitted);
@ -95,8 +121,7 @@ admissions_control_decide(uint64_t admissions_estimate)
admissions_control_add(admissions_estimate);
work_admitted = admissions_estimate;
}
#endif /* ADMISSIONS_CONTROL */
return work_admitted;
}
#endif /* ADMISSIONS_CONTROL */

@ -0,0 +1,56 @@
#include "admissions_control.h"
#include "admissions_info.h"
#include "debuglog.h"
#include "perf_window.h"
/**
* Initializes perf window
* @param admissions_info
*/
void
admissions_info_initialize(struct admissions_info *admissions_info, uint8_t percentile, uint64_t expected_execution,
uint64_t relative_deadline)
{
#ifdef ADMISSIONS_CONTROL
assert(relative_deadline > 0);
assert(expected_execution > 0);
admissions_info->relative_deadline = relative_deadline;
admissions_info->estimate = admissions_control_calculate_estimate(expected_execution, relative_deadline);
debuglog("Initial Estimate: %lu\n", admissions_info->estimate);
assert(admissions_info != NULL);
perf_window_initialize(&admissions_info->perf_window);
if (unlikely(percentile < 50 || percentile > 99)) panic("Invalid admissions percentile");
admissions_info->percentile = percentile;
admissions_info->control_index = PERF_WINDOW_CAPACITY * percentile / 100;
#ifdef LOG_ADMISSIONS_CONTROL
debuglog("Percentile: %u\n", admissions_info->percentile);
debuglog("Control Index: %d\n", admissions_info->control_index);
#endif
#endif
}
/*
* Adds an execution value to the perf window and calculates and caches and updated estimate
* @param admissions_info
* @param execution_duration
*/
void
admissions_info_update(struct admissions_info *admissions_info, uint64_t execution_duration)
{
#ifdef ADMISSIONS_CONTROL
struct perf_window *perf_window = &admissions_info->perf_window;
lock_node_t node = {};
lock_lock(&perf_window->lock, &node);
perf_window_add(perf_window, execution_duration);
uint64_t estimated_execution = perf_window_get_percentile(perf_window, admissions_info->percentile,
admissions_info->control_index);
admissions_info->estimate = admissions_control_calculate_estimate(estimated_execution,
admissions_info->relative_deadline);
lock_unlock(&perf_window->lock, &node);
#endif
}

@ -1,18 +1,25 @@
#include <threads.h>
#include <setjmp.h>
#include <threads.h>
#include "current_sandbox.h"
#include "sandbox_functions.h"
#include "sandbox_set_as_asleep.h"
#include "sandbox_set_as_complete.h"
#include "sandbox_set_as_error.h"
#include "sandbox_set_as_returned.h"
#include "sandbox_set_as_running_sys.h"
#include "sandbox_set_as_complete.h"
#include "sandbox_set_as_running_user.h"
#include "sandbox_set_as_running_sys.h"
#include "scheduler.h"
#include "http_session.h"
#include "software_interrupt.h"
#include "wasi.h"
extern struct http_session *g_session;
extern struct tenant *g_tenant;
extern int g_client_socket;
extern struct sockaddr *g_client_address;
thread_local struct sandbox *worker_thread_current_sandbox = NULL;
/**
@ -62,6 +69,34 @@ current_sandbox_exit()
sandbox_state_stringify(exiting_sandbox->state));
}
/* generate a new request and enqueue it to the global queue */
assert(g_tenant != NULL);
struct tenant *tenant = g_tenant;
uint64_t request_arrival_timestamp = __getcycles();
http_total_increment_request();
/* Allocate http session */
//struct http_session *session = http_session_alloc(g_client_socket, (const struct sockaddr *)&g_client_address, tenant, request_arrival_timestamp);
//assert(session != NULL);
//http_session_copy(session, g_session);
struct http_session *session = g_session;
assert(session->route != NULL);
struct sandbox *sandbox = sandbox_alloc(session->route->module, session, session->route, session->tenant, 1);
if (unlikely(sandbox == NULL)) {
printf("Failed to allocate sandbox\n");
exit(-1);
}
/* If the global request scheduler is full, return a 429 to the client */
if (unlikely(global_request_scheduler_add(sandbox) == NULL)) {
printf("Failed to add sandbox to global queue\n");
exit(-1);
}
/****************************end**************************/
scheduler_cooperative_sched(true);
/* The scheduler should never switch back to completed sandboxes */
@ -193,5 +228,5 @@ current_sandbox_start(void)
current_sandbox_wasm_trap_handler(rc);
}
if (sandbox->module->type == APP_MODULE) current_sandbox_fini();
current_sandbox_fini();
}

@ -1,20 +1,20 @@
#include <stdlib.h>
#include "current_sandbox.h"
#include "wasm_memory.h"
#include "wasm_module_instance.h"
#include "wasm_memory.h"
thread_local struct wasm_module_instance sledge_abi__current_wasm_module_instance = {
.abi.memory =
(struct sledge_abi__wasm_memory){
.size = 0,
.max = 0,
.capacity = 0,
.buffer = NULL,
},
.abi.table = NULL,
.abi.wasmg_0 = 0xDEADBEEF,
.wasi_context = NULL,
.abi.memory =
(struct sledge_abi__wasm_memory){
.size = 0,
.max = 0,
.capacity = 0,
.buffer = NULL,
},
.abi.table = NULL,
.abi.wasmg_0 = 0xDEADBEEF,
.wasi_context = NULL,
};
void

@ -1,50 +0,0 @@
#ifdef EXECUTION_HISTOGRAM
#include "execution_histogram.h"
#include "debuglog.h"
#include "perf_window.h"
/**
* Initializes execution_histogram and its perf window
* @param execution_histogram
*/
void
execution_histogram_initialize(struct execution_histogram *execution_histogram, uint8_t percentile,
uint64_t expected_execution)
{
assert(expected_execution > 0);
execution_histogram->estimated_execution = expected_execution;
assert(execution_histogram != NULL);
perf_window_initialize(&execution_histogram->perf_window);
if (unlikely(percentile < 50 || percentile > 99)) panic("Invalid percentile");
execution_histogram->percentile = percentile;
execution_histogram->control_index = PERF_WINDOW_CAPACITY * percentile / 100;
#ifdef LOG_EXECUTION_HISTOGRAM
debuglog("Percentile: %u\n", execution_histogram->percentile);
debuglog("Control Index: %d\n", execution_histogram->control_index);
#endif
}
/*
* Adds an execution value to the perf window
* @param execution_histogram
* @param execution_duration
*/
void
execution_histogram_update(struct execution_histogram *execution_histogram, uint64_t execution_duration)
{
struct perf_window *perf_window = &execution_histogram->perf_window;
lock_node_t node = {};
lock_lock(&perf_window->lock, &node);
perf_window_add(perf_window, execution_duration);
uint64_t estimated_execution = perf_window_get_percentile(perf_window, execution_histogram->percentile,
execution_histogram->control_index);
execution_histogram->estimated_execution = estimated_execution;
lock_unlock(&perf_window->lock, &node);
}
#endif

@ -24,9 +24,9 @@ uninitialized_peek()
/* The global of our polymorphic interface */
static struct global_request_scheduler_config global_request_scheduler = {.add_fn = uninitialized_add,
.remove_fn = uninitialized_remove,
.peek_fn = uninitialized_peek};
static struct global_request_scheduler_config global_request_scheduler = { .add_fn = uninitialized_add,
.remove_fn = uninitialized_remove,
.peek_fn = uninitialized_peek };
/**
* Initializes the polymorphic interface with a concrete implementation

@ -1,8 +1,8 @@
#include "global_request_scheduler_deque.h"
#include "global_request_scheduler.h"
#include "global_request_scheduler_deque.h"
#include "runtime.h"
#define GLOBAL_REQUEST_SCHEDULER_DEQUE_CAPACITY (1 << 12)
#define GLOBAL_REQUEST_SCHEDULER_DEQUE_CAPACITY (1 << 19)
static struct deque_sandbox *global_request_scheduler_deque;
@ -57,10 +57,11 @@ global_request_scheduler_deque_initialize()
deque_init_sandbox(global_request_scheduler_deque, GLOBAL_REQUEST_SCHEDULER_DEQUE_CAPACITY);
/* Register Function Pointers for Abstract Scheduling API */
struct global_request_scheduler_config config = {.add_fn = global_request_scheduler_deque_add,
.remove_fn = global_request_scheduler_deque_remove,
.remove_if_earlier_fn =
global_request_scheduler_deque_remove_if_earlier};
struct global_request_scheduler_config config = {
.add_fn = global_request_scheduler_deque_add,
.remove_fn = global_request_scheduler_deque_remove,
.remove_if_earlier_fn = global_request_scheduler_deque_remove_if_earlier
};
global_request_scheduler_initialize(&config);
}

@ -19,7 +19,7 @@ global_request_scheduler_minheap_add(struct sandbox *sandbox)
{
assert(sandbox);
assert(global_request_scheduler_minheap);
if (unlikely(!listener_thread_is_running())) panic("%s is only callable by the listener thread\n", __func__);
//if (unlikely(!listener_thread_is_running())) panic("%s is only callable by the listener thread\n", __func__);
int return_code = priority_queue_enqueue(global_request_scheduler_minheap, sandbox);
@ -43,10 +43,10 @@ global_request_scheduler_minheap_remove(struct sandbox **removed_sandbox)
* @returns 0 if successful, -ENOENT if empty or if request isn't earlier than target_deadline
*/
int
global_request_scheduler_minheap_remove_if_earlier(struct sandbox **removed_sandbox, uint64_t target_latest_start)
global_request_scheduler_minheap_remove_if_earlier(struct sandbox **removed_sandbox, uint64_t target_deadline)
{
return priority_queue_dequeue_if_earlier(global_request_scheduler_minheap, (void **)removed_sandbox,
target_latest_start);
target_deadline);
}
/**
@ -65,8 +65,6 @@ uint64_t
sandbox_get_priority_fn(void *element)
{
struct sandbox *sandbox = (struct sandbox *)element;
if (scheduler == SCHEDULER_SJF) return sandbox->remaining_exec;
assert(scheduler == SCHEDULER_EDF);
return sandbox->absolute_deadline;
};
@ -77,13 +75,14 @@ sandbox_get_priority_fn(void *element)
void
global_request_scheduler_minheap_initialize()
{
global_request_scheduler_minheap = priority_queue_initialize(4096, true, sandbox_get_priority_fn);
global_request_scheduler_minheap = priority_queue_initialize(4096000, true, sandbox_get_priority_fn);
struct global_request_scheduler_config config = {.add_fn = global_request_scheduler_minheap_add,
.remove_fn = global_request_scheduler_minheap_remove,
.remove_if_earlier_fn =
global_request_scheduler_minheap_remove_if_earlier,
.peek_fn = global_request_scheduler_minheap_peek};
struct global_request_scheduler_config config = {
.add_fn = global_request_scheduler_minheap_add,
.remove_fn = global_request_scheduler_minheap_remove,
.remove_if_earlier_fn = global_request_scheduler_minheap_remove_if_earlier,
.peek_fn = global_request_scheduler_minheap_peek
};
global_request_scheduler_initialize(&config);
}

@ -230,11 +230,12 @@ global_request_scheduler_mtds_initialize()
lock_init(&global_lock);
struct global_request_scheduler_config config = {.add_fn = global_request_scheduler_mtds_add,
.remove_fn = global_request_scheduler_mtds_remove,
.remove_if_earlier_fn =
global_request_scheduler_mtds_remove_if_earlier,
.peek_fn = global_request_scheduler_mtds_peek};
struct global_request_scheduler_config config = {
.add_fn = global_request_scheduler_mtds_add,
.remove_fn = global_request_scheduler_mtds_remove,
.remove_if_earlier_fn = global_request_scheduler_mtds_remove_if_earlier,
.peek_fn = global_request_scheduler_mtds_peek
};
global_request_scheduler_initialize(&config);
}

@ -3,8 +3,8 @@
#include "debuglog.h"
#include "http.h"
#include "http_parser_settings.h"
#include "http_request.h"
#include "http_parser_settings.h"
#include "likely.h"
http_parser_settings runtime_http_parser_settings;
@ -211,7 +211,7 @@ http_parser_settings_on_header_end(http_parser *parser)
}
}
const char *http_methods[] = {"OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT"};
const char *http_methods[] = { "OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT" };
/**
* http-parser callback called for HTTP Bodies

@ -18,8 +18,8 @@ http_session_perf_log_print_entry(struct http_session *http_session)
const uint64_t sent_duration = http_session->response_sent_timestamp - http_session->response_takeoff_timestamp;
const uint64_t total_lifetime = http_session->response_sent_timestamp - http_session->request_arrival_timestamp;
fprintf(http_session_perf_log, "%s,%s,%u,%lu,%lu,%lu,%lu,%lu,%lu,%u\n", http_session->tenant->name,
fprintf(http_session_perf_log, "%s,%s,%u,%lu,%lu,%lu,%lu,%lu,%u\n", http_session->tenant->name,
http_session->http_request.full_url, http_session->state, http_session->response_header_written,
http_session->response_body_written, receive_duration, sent_duration, total_lifetime,
http_session->preprocessing_duration, runtime_processor_speed_MHz);
runtime_processor_speed_MHz);
}

@ -112,10 +112,8 @@ wasi_context_init(wasi_options_t *options)
}
}
/* Seed Random
* Commented out as a temporary fix for the mutex blocking delay srandom causes in libc.
*/
// srandom(time(NULL));
/* Seed Random */
srandom(time(NULL));
/* TODO: Preopens */
@ -662,7 +660,7 @@ wasi_snapshot_preview1_backing_fd_read(wasi_context_t *context, __wasi_fd_t fd,
if (fd == STDIN_FILENO) {
struct sandbox *current_sandbox = current_sandbox_get();
struct http_request *current_request = &current_sandbox->http->http_request;
int old_read = current_request->cursor;
int old_read = current_sandbox->cursor;
int bytes_to_read = current_request->body_length - old_read;
assert(current_request->body_length >= 0);
@ -671,13 +669,13 @@ wasi_snapshot_preview1_backing_fd_read(wasi_context_t *context, __wasi_fd_t fd,
if (bytes_to_read == 0) goto done;
int amount_to_copy = iovs[i].buf_len > bytes_to_read ? bytes_to_read : iovs[i].buf_len;
memcpy(iovs[i].buf, current_request->body + current_request->cursor, amount_to_copy);
current_request->cursor += amount_to_copy;
bytes_to_read = current_request->body_length - current_request->cursor;
memcpy(iovs[i].buf, current_request->body + current_sandbox->cursor, amount_to_copy);
current_sandbox->cursor += amount_to_copy;
bytes_to_read = current_request->body_length - current_sandbox->cursor;
}
done:
*nwritten_retptr = current_request->cursor - old_read;
*nwritten_retptr = current_sandbox->cursor - old_read;
return __WASI_ERRNO_SUCCESS;
}
@ -798,7 +796,8 @@ wasi_snapshot_preview1_backing_fd_write(wasi_context_t *context, __wasi_fd_t fd,
debuglog("STDERR from Sandbox: %.*s", iovs[i].buf_len, iovs[i].buf);
}
#endif
rc = fwrite(iovs[i].buf, 1, iovs[i].buf_len, s->http->response_body.handle);
//rc = fwrite(iovs[i].buf, 1, iovs[i].buf_len, s->http->response_body.handle);
rc = fwrite(iovs[i].buf, 1, iovs[i].buf_len, s->response_body.handle);
if (rc != iovs[i].buf_len) return __WASI_ERRNO_FBIG;
nwritten += rc;

@ -2,18 +2,27 @@
#include <unistd.h>
#include "arch/getcycles.h"
#include "execution_regression.h"
#include "global_request_scheduler.h"
#include "http_session_perf_log.h"
#include "listener_thread.h"
#include "metrics_server.h"
#include "module.h"
#include "runtime.h"
#include "sandbox_functions.h"
#include "sandbox_perf_log.h"
#include "tcp_session.h"
#include "tenant.h"
#include "tenant_functions.h"
#include "http_session_perf_log.h"
extern thread_local int thread_id;
extern void http_session_copy(struct http_session *dest, struct http_session *source);
/////////////////xiaosu for test//////////////////
extern bool first_request_comming;
time_t t_start;
struct http_session *g_session = NULL;
struct tenant *g_tenant = NULL;
int g_client_socket = -1;
struct sockaddr *g_client_address = NULL;
////////////////xiaosu end for test///////////////
static void listener_thread_unregister_http_session(struct http_session *http);
static void panic_on_epoll_error(struct epoll_event *evt);
@ -170,6 +179,14 @@ panic_on_epoll_error(struct epoll_event *evt)
static void
on_client_request_arrival(int client_socket, const struct sockaddr *client_address, struct tenant *tenant)
{
if (g_client_socket == -1) {
g_client_socket = client_socket;
}
if (g_client_address == NULL) {
g_client_address = client_address;
}
uint64_t request_arrival_timestamp = __getcycles();
http_total_increment_request();
@ -193,36 +210,18 @@ on_client_request_arrival(int client_socket, const struct sockaddr *client_addre
static void
on_client_request_receiving(struct http_session *session)
{
if (first_request_comming == false){
t_start = time(NULL);
first_request_comming = true;
}
/* Read HTTP request */
int rc = http_session_receive_request(session, (void_star_cb)listener_thread_register_http_session);
/* Check if the route is accurate only when the URL is downloaded. Stop downloading if inaccurate. */
if (session->route == NULL && strlen(session->http_request.full_url) > 0) {
struct route *route = http_router_match_route(&session->tenant->router, session->http_request.full_url);
if (route == NULL) {
debuglog("Did not match any routes\n");
session->state = HTTP_SESSION_EXECUTION_COMPLETE;
http_session_set_response_header(session, 404);
on_client_response_header_sending(session);
return;
}
session->route = route;
}
if (rc == 0) {
#ifdef EXECUTION_REGRESSION
if (!session->did_preprocessing) tenant_preprocess(session);
#endif
if (likely(rc == 0)) {
on_client_request_received(session);
return;
} else if (rc == -EAGAIN) {
/* session blocked and registered to epoll, so continue to next handle */
#ifdef EXECUTION_REGRESSION
/* try tenant preprocessing if min 4k Bytes received */
if (!session->did_preprocessing && session->http_request.body_length_read > 4096)
tenant_preprocess(session);
#endif
} else if (unlikely(rc == -EAGAIN)) {
/* session blocked and registered to epoll so continue to next handle */
return;
} else if (rc < 0) {
debuglog("Failed to receive or parse request\n");
@ -240,32 +239,40 @@ on_client_request_received(struct http_session *session)
{
assert(session->state == HTTP_SESSION_RECEIVED_REQUEST);
session->request_downloaded_timestamp = __getcycles();
struct route *route = session->route;
uint64_t estimated_execution = route->execution_histogram.estimated_execution;
uint64_t work_admitted = 1;
#ifdef EXECUTION_REGRESSION
estimated_execution = get_regression_prediction(session);
#endif
struct route *route = http_router_match_route(&session->tenant->router, session->http_request.full_url);
if (route == NULL) {
debuglog("Did not match any routes\n");
session->state = HTTP_SESSION_EXECUTION_COMPLETE;
http_session_set_response_header(session, 404);
on_client_response_header_sending(session);
return;
}
session->route = route;
#ifdef ADMISSIONS_CONTROL
/*
* Perform admissions control.
* If 0, workload was rejected, so close with 429 "Too Many Requests" and continue
* TODO: Consider providing a Retry-After header
*/
uint64_t admissions_estimate = admissions_control_calculate_estimate(estimated_execution,
route->relative_deadline);
work_admitted = admissions_control_decide(admissions_estimate);
uint64_t work_admitted = admissions_control_decide(route->admissions_info.estimate);
if (work_admitted == 0) {
session->state = HTTP_SESSION_EXECUTION_COMPLETE;
http_session_set_response_header(session, 429);
on_client_response_header_sending(session);
return;
}
#endif
/* Allocate a Sandbox */
session->state = HTTP_SESSION_EXECUTING;
if (g_session == NULL) {
/* Allocate HTTP Session */
g_session = http_session_alloc(session->socket, (const struct sockaddr *)&(session->client_address),
session->tenant, session->request_arrival_timestamp);
http_session_copy(g_session, session);
}
struct sandbox *sandbox = sandbox_alloc(route->module, session, route, session->tenant, work_admitted);
if (unlikely(sandbox == NULL)) {
debuglog("Failed to allocate sandbox\n");
@ -275,15 +282,9 @@ on_client_request_received(struct http_session *session)
return;
}
sandbox->remaining_exec = estimated_execution;
/* If the global request scheduler is full, return a 429 to the client */
if (unlikely(global_request_scheduler_add(sandbox) == NULL)) {
// debuglog("Failed to add sandbox to global queue\n");
sandbox->response_code = 4290;
sandbox->state = SANDBOX_ERROR;
sandbox_perf_log_print_entry(sandbox);
sandbox->http = NULL;
debuglog("Failed to add sandbox to global queue\n");
sandbox_free(sandbox);
session->state = HTTP_SESSION_EXECUTION_COMPLETE;
http_session_set_response_header(session, 429);
@ -347,6 +348,9 @@ on_tenant_socket_epoll_event(struct epoll_event *evt)
struct tenant *tenant = evt->data.ptr;
assert(tenant);
if (g_tenant == NULL) {
g_tenant = tenant;
}
/* Accept Client Request as a nonblocking socket, saving address information */
struct sockaddr_in client_address;
@ -431,6 +435,7 @@ on_client_socket_epoll_event(struct epoll_event *evt)
noreturn void *
listener_thread_main(void *dummy)
{
thread_id = 200;
struct epoll_event epoll_events[RUNTIME_MAX_EPOLL_EVENTS];
metrics_server_init();

@ -6,6 +6,7 @@
#include "local_runqueue.h"
thread_local uint32_t total_local_requests = 0;
static struct local_runqueue_config local_runqueue;
#ifdef LOG_LOCAL_RUNQUEUE
@ -27,6 +28,7 @@ void
local_runqueue_add(struct sandbox *sandbox)
{
assert(local_runqueue.add_fn != NULL);
total_local_requests++;
#ifdef LOG_LOCAL_RUNQUEUE
local_runqueue_count++;
#endif

@ -2,8 +2,8 @@
#include "current_sandbox.h"
#include "global_request_scheduler.h"
#include "local_runqueue.h"
#include "local_runqueue_list.h"
#include "local_runqueue.h"
#include "sandbox_functions.h"
thread_local static struct ps_list_head local_runqueue_list;
@ -81,9 +81,9 @@ local_runqueue_list_initialize()
ps_list_head_init(&local_runqueue_list);
/* Register Function Pointers for Abstract Scheduling API */
struct local_runqueue_config config = {.add_fn = local_runqueue_list_append,
.is_empty_fn = local_runqueue_list_is_empty,
.delete_fn = local_runqueue_list_remove,
.get_next_fn = local_runqueue_list_get_next};
struct local_runqueue_config config = { .add_fn = local_runqueue_list_append,
.is_empty_fn = local_runqueue_list_is_empty,
.delete_fn = local_runqueue_list_remove,
.get_next_fn = local_runqueue_list_get_next };
local_runqueue_initialize(&config);
};

@ -9,9 +9,11 @@
#include "local_runqueue_minheap.h"
#include "panic.h"
#include "priority_queue.h"
#include "runtime.h"
#include "sandbox_functions.h"
#include "runtime.h"
uint64_t total_held[1024] = {0};
uint64_t longest_held[1024] = {0};
thread_local static struct priority_queue *local_runqueue_minheap;
/**
@ -84,10 +86,10 @@ local_runqueue_minheap_initialize()
local_runqueue_minheap = priority_queue_initialize(RUNTIME_RUNQUEUE_SIZE, false, sandbox_get_priority);
/* Register Function Pointers for Abstract Scheduling API */
struct local_runqueue_config config = {.add_fn = local_runqueue_minheap_add,
.is_empty_fn = local_runqueue_minheap_is_empty,
.delete_fn = local_runqueue_minheap_delete,
.get_next_fn = local_runqueue_minheap_get_next};
struct local_runqueue_config config = { .add_fn = local_runqueue_minheap_add,
.is_empty_fn = local_runqueue_minheap_is_empty,
.delete_fn = local_runqueue_minheap_delete,
.get_next_fn = local_runqueue_minheap_get_next };
local_runqueue_initialize(&config);
}

@ -9,9 +9,9 @@
#include "local_runqueue_mtds.h"
#include "panic.h"
#include "priority_queue.h"
#include "runtime.h"
#include "sandbox_functions.h"
#include "tenant_functions.h"
#include "runtime.h"
thread_local static struct priority_queue *local_runqueue_mtds_guaranteed;
thread_local static struct priority_queue *local_runqueue_mtds_default;
@ -172,10 +172,10 @@ local_runqueue_mtds_initialize()
perworker_tenant_get_priority);
/* Register Function Pointers for Abstract Scheduling API */
struct local_runqueue_config config = {.add_fn = local_runqueue_mtds_add,
.is_empty_fn = local_runqueue_mtds_is_empty,
.delete_fn = local_runqueue_mtds_delete,
.get_next_fn = local_runqueue_mtds_get_next};
struct local_runqueue_config config = { .add_fn = local_runqueue_mtds_add,
.is_empty_fn = local_runqueue_mtds_is_empty,
.delete_fn = local_runqueue_mtds_delete,
.get_next_fn = local_runqueue_mtds_get_next };
local_runqueue_initialize(&config);
}

@ -2,25 +2,25 @@
#include <dlfcn.h>
#include <math.h>
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <sched.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#ifdef LOG_TO_FILE
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#endif
#include "debuglog.h"
#include "json_parse.h"
#include "pretty_print.h"
#include "debuglog.h"
#include "listener_thread.h"
#include "panic.h"
#include "pretty_print.h"
#include "runtime.h"
#include "sandbox_perf_log.h"
#include "sandbox_types.h"
@ -35,12 +35,14 @@ uint32_t runtime_first_worker_processor = 1;
uint32_t runtime_processor_speed_MHz = 0;
uint32_t runtime_total_online_processors = 0;
uint32_t runtime_worker_threads_count = 0;
bool first_request_comming = false;
thread_local int thread_id = -1;
enum RUNTIME_SIGALRM_HANDLER runtime_sigalrm_handler = RUNTIME_SIGALRM_HANDLER_BROADCAST;
bool runtime_preemption_enabled = true;
bool runtime_worker_spinloop_pause_enabled = false;
uint32_t runtime_quantum_us = 1000; /* 1ms */
uint32_t runtime_quantum_us = 5000; /* 5ms */
uint64_t runtime_boot_timestamp;
pid_t runtime_pid = 0;
@ -67,15 +69,20 @@ runtime_allocate_available_cores()
pretty_print_key_value("Core Count (Online)", "%u\n", runtime_total_online_processors);
/* If more than two cores are available, leave core 0 free to run OS tasks */
if (runtime_total_online_processors > 2) {
runtime_first_worker_processor = 2;
max_possible_workers = runtime_total_online_processors - 2;
} else if (runtime_total_online_processors == 2) {
runtime_first_worker_processor = 1;
max_possible_workers = runtime_total_online_processors - 1;
char* first_core_id = getenv("SLEDGE_FIRST_COREID");
if (first_core_id != NULL) {
runtime_first_worker_processor = atoi(first_core_id);
} else {
panic("Runtime requires at least two cores!");
/* If more than two cores are available, leave core 0 free to run OS tasks */
if (runtime_total_online_processors > 2) {
runtime_first_worker_processor = 2;
max_possible_workers = runtime_total_online_processors - 2;
} else if (runtime_total_online_processors == 2) {
runtime_first_worker_processor = 1;
max_possible_workers = runtime_total_online_processors - 1;
} else {
panic("Runtime requires at least two cores!");
}
}
@ -105,7 +112,7 @@ runtime_allocate_available_cores()
static inline void
runtime_get_processor_speed_MHz(void)
{
char *proc_mhz_raw = getenv("SLEDGE_PROC_MHZ");
char *proc_mhz_raw = getenv("PROC_MHZ");
FILE *cmd = NULL;
if (proc_mhz_raw != NULL) {
@ -116,7 +123,7 @@ runtime_get_processor_speed_MHz(void)
usleep(200000); /* wait a bit for the workers to launch for more accuracy */
/* Get the average of the cpufreqs only for worker cores (no event core and reserved) */
char command[128] = {0};
char command[128] = { 0 };
sprintf(command, "grep '^cpu MHz' /proc/cpuinfo | sed -n '%u,%up' | \
awk '{ total += $4; count++ } END { print total/count }'",
runtime_first_worker_processor + 1,
@ -127,7 +134,6 @@ runtime_get_processor_speed_MHz(void)
char buff[16];
size_t n = fread(buff, 1, sizeof(buff) - 1, cmd);
buff[n] = '\0';
pclose(cmd);
float processor_speed_MHz;
n = sscanf(buff, "%f", &processor_speed_MHz);
@ -140,6 +146,7 @@ runtime_get_processor_speed_MHz(void)
pretty_print_key_value("Worker CPU Freq", "%u MHz\n", runtime_processor_speed_MHz);
done:
pclose(cmd);
return;
err:
goto done;
@ -208,12 +215,10 @@ runtime_configure()
scheduler = SCHEDULER_MTDS;
} else if (strcmp(scheduler_policy, "EDF") == 0) {
scheduler = SCHEDULER_EDF;
} else if (strcmp(scheduler_policy, "SJF") == 0) {
scheduler = SCHEDULER_SJF;
} else if (strcmp(scheduler_policy, "FIFO") == 0) {
scheduler = SCHEDULER_FIFO;
} else {
panic("Invalid scheduler policy: %s. Must be {MTDBF|MTDS|EDF|SJF|FIFO}\n", scheduler_policy);
panic("Invalid scheduler policy: %s. Must be {MTDBF|MTDS|EDF|FIFO}\n", scheduler_policy);
}
pretty_print_key_value("Scheduler Policy", "%s\n", scheduler_print(scheduler));
@ -286,18 +291,6 @@ log_compiletime_config()
pretty_print_key_disabled("Admissions Control");
#endif
#ifdef EXECUTION_HISTOGRAM
pretty_print_key_enabled("Execution Histogram");
#else
pretty_print_key_disabled("Execution Histogram");
#endif
#ifdef EXECUTION_REGRESSION
pretty_print_key_enabled("Execution Regression");
#else
pretty_print_key_disabled("Execution Regression");
#endif
/* Debugging Flags */
printf("Static Compiler Flags (Debugging):\n");
@ -490,6 +483,8 @@ main(int argc, char **argv)
printf("Runtime Environment:\n");
runtime_processor_speed_MHz = 1500;
runtime_set_resource_limits_to_max();
runtime_allocate_available_cores();
runtime_configure();
@ -498,7 +493,7 @@ main(int argc, char **argv)
listener_thread_initialize();
runtime_start_runtime_worker_threads();
runtime_get_processor_speed_MHz();
//runtime_get_processor_speed_MHz();
runtime_configure_worker_spinloop_pause();
software_interrupt_arm_timer();

@ -11,8 +11,8 @@
#include "metrics_server.h"
#include "proc_stat.h"
#include "runtime.h"
#include "sandbox_state.h"
#include "sandbox_total.h"
#include "sandbox_state.h"
#include "tcp_server.h"
/* We run threads on the "reserved OS core" using blocking semantics */

@ -44,8 +44,7 @@ module_init(struct module *module, char *path)
rc = sledge_abi_symbols_init(&module->abi, path);
if (rc != 0) goto err;
module->pools = calloc((module->type == APP_MODULE ? runtime_worker_threads_count : 1),
sizeof(struct module_pool));
module->pools = calloc(runtime_worker_threads_count, sizeof(struct module_pool));
module->path = path;
@ -107,7 +106,7 @@ module_free(struct module *module)
*/
struct module *
module_alloc(char *path, enum module_type type)
module_alloc(char *path)
{
size_t alignment = (size_t)CACHE_PAD;
size_t size_to_alloc = (size_t)round_to_cache_pad(sizeof(struct module));
@ -121,7 +120,6 @@ module_alloc(char *path, enum module_type type)
};
memset(module, 0, size_to_alloc);
module->type = type;
int rc = module_init(module, path);
if (rc < 0) goto init_err;

@ -1,13 +1,14 @@
#include <arpa/inet.h>
#include <assert.h>
#include <pthread.h>
#include <sched.h>
#include <signal.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <pthread.h>
#include "admissions_control.h"
#include "arch/context.h"
@ -18,10 +19,10 @@
#include "listener_thread.h"
#include "module.h"
#include "runtime.h"
#include "sandbox_perf_log.h"
#include "sandbox_total.h"
#include "scheduler.h"
#include "software_interrupt.h"
#include "sandbox_perf_log.h"
/***************************
* Shared Process State *
@ -62,8 +63,8 @@ runtime_set_resource_limits_to_max()
char lim[uint64_t_max_digits + 1];
char max[uint64_t_max_digits + 1];
uint64_t resources[] = {RLIMIT_DATA, RLIMIT_NOFILE};
char *resource_names[] = {"RLIMIT_DATA", "RLIMIT_NOFILE"};
uint64_t resources[] = { RLIMIT_DATA, RLIMIT_NOFILE };
char *resource_names[] = { "RLIMIT_DATA", "RLIMIT_NOFILE" };
for (int i = 0; i < sizeof(resources) / sizeof(resources[0]); i++) {
int resource = resources[i];
@ -117,11 +118,7 @@ runtime_initialize(void)
signal(SIGQUIT, runtime_cleanup);
http_parser_settings_initialize();
#ifdef ADMISSIONS_CONTROL
/* Admissions Control Setup */
admissions_control_initialize();
#endif
}
static void

@ -8,9 +8,9 @@
#include "pool.h"
#include "runtime.h"
#include "sandbox_functions.h"
#include "sandbox_set_as_allocated.h"
#include "sandbox_set_as_error.h"
#include "sandbox_set_as_initialized.h"
#include "sandbox_set_as_allocated.h"
#include "sandbox_total.h"
#include "wasm_memory.h"
#include "wasm_stack.h"
@ -25,6 +25,21 @@ sandbox_log_allocation(struct sandbox *sandbox)
#endif
}
int
init_response_body(struct sandbox *sandbox)
{
if (sandbox->response_body.data == NULL) {
sandbox->response_body.size = 0;
int rc = auto_buf_init(&sandbox->response_body);
if (rc < 0) {
printf("failed to init http body autobuf, exit\n");
exit(-1);
}
}
return 0;
}
/**
* Allocates a WebAssembly linear memory for a sandbox based on the starting_pages and max_pages globals present in
* the associated *.so module
@ -94,7 +109,8 @@ sandbox_prepare_execution_environment(struct sandbox *sandbox)
int rc;
rc = http_session_init_response_body(sandbox->http);
//rc = http_session_init_response_body(sandbox->http);
rc = init_response_body(sandbox);
if (rc < 0) {
error_message = "failed to allocate response body";
goto err_globals_allocation_failed;
@ -135,6 +151,14 @@ err_http_allocation_failed:
goto done;
}
void
deinit_response_body(struct sandbox *sandbox)
{
auto_buf_deinit(&sandbox->response_body);
}
void
sandbox_init(struct sandbox *sandbox, struct module *module, struct http_session *session, struct route *route,
struct tenant *tenant, uint64_t admissions_estimate)
@ -148,14 +172,12 @@ sandbox_init(struct sandbox *sandbox, struct module *module, struct http_session
ps_list_init_d(sandbox);
/* Allocate HTTP session structure */
assert(session);
//assert(session);
sandbox->http = session;
sandbox->tenant = tenant;
sandbox->route = route;
sandbox->absolute_deadline = sandbox->timestamp_of.allocation + sandbox->route->relative_deadline;
sandbox->payload_size = session->http_request.body_length;
sandbox->regression_param = session->regression_param;
/*
* Admissions Control State
@ -213,6 +235,8 @@ sandbox_deinit(struct sandbox *sandbox)
/* Linear Memory and Guard Page should already have been munmaped and set to NULL */
assert(sandbox->memory == NULL);
deinit_response_body(sandbox);
if (likely(sandbox->stack != NULL)) sandbox_free_stack(sandbox);
if (likely(sandbox->globals.buffer != NULL)) sandbox_free_globals(sandbox);
if (likely(sandbox->wasi_context != NULL)) wasi_context_destroy(sandbox->wasi_context);

@ -9,18 +9,19 @@
const char *sandbox_state_labels[SANDBOX_STATE_COUNT] = {
[SANDBOX_UNINITIALIZED] = "Uninitialized",
[SANDBOX_ALLOCATED] = "Allocated",
[SANDBOX_INITIALIZED] = "Initialized",
[SANDBOX_RUNNABLE] = "Runnable",
[SANDBOX_INTERRUPTED] = "Interrupted",
[SANDBOX_PREEMPTED] = "Preempted",
[SANDBOX_RUNNING_SYS] = "Running Sys",
[SANDBOX_RUNNING_USER] = "Running User",
[SANDBOX_ASLEEP] = "Asleep",
[SANDBOX_RETURNED] = "Returned",
[SANDBOX_COMPLETE] = "Complete",
[SANDBOX_ERROR] = "Error"};
[SANDBOX_UNINITIALIZED] = "Uninitialized",
[SANDBOX_ALLOCATED] = "Allocated",
[SANDBOX_INITIALIZED] = "Initialized",
[SANDBOX_RUNNABLE] = "Runnable",
[SANDBOX_INTERRUPTED] = "Interrupted",
[SANDBOX_PREEMPTED] = "Preempted",
[SANDBOX_RUNNING_SYS] = "Running Sys",
[SANDBOX_RUNNING_USER] = "Running User",
[SANDBOX_ASLEEP] = "Asleep",
[SANDBOX_RETURNED] = "Returned",
[SANDBOX_COMPLETE] = "Complete",
[SANDBOX_ERROR] = "Error"
};
#ifdef SANDBOX_STATE_TOTALS
_Atomic uint32_t sandbox_state_totals[SANDBOX_STATE_COUNT];

@ -9,31 +9,33 @@ sandbox_state_transition_hook_default(struct sandbox *sandbox)
/* Called while nonpreemptable */
sandbox_state_transition_hook_t sandbox_state_transition_to_hooks[SANDBOX_STATE_COUNT] = {
[SANDBOX_UNINITIALIZED] = sandbox_state_transition_hook_default,
[SANDBOX_ALLOCATED] = sandbox_state_transition_hook_default,
[SANDBOX_INITIALIZED] = sandbox_state_transition_hook_default,
[SANDBOX_RUNNABLE] = sandbox_state_transition_hook_default,
[SANDBOX_INTERRUPTED] = sandbox_state_transition_hook_default,
[SANDBOX_PREEMPTED] = sandbox_state_transition_hook_default,
[SANDBOX_RUNNING_SYS] = sandbox_state_transition_hook_default,
[SANDBOX_RUNNING_USER] = sandbox_state_transition_hook_default,
[SANDBOX_ASLEEP] = sandbox_state_transition_hook_default,
[SANDBOX_RETURNED] = sandbox_state_transition_hook_default,
[SANDBOX_COMPLETE] = sandbox_state_transition_hook_default,
[SANDBOX_ERROR] = sandbox_state_transition_hook_default};
[SANDBOX_UNINITIALIZED] = sandbox_state_transition_hook_default,
[SANDBOX_ALLOCATED] = sandbox_state_transition_hook_default,
[SANDBOX_INITIALIZED] = sandbox_state_transition_hook_default,
[SANDBOX_RUNNABLE] = sandbox_state_transition_hook_default,
[SANDBOX_INTERRUPTED] = sandbox_state_transition_hook_default,
[SANDBOX_PREEMPTED] = sandbox_state_transition_hook_default,
[SANDBOX_RUNNING_SYS] = sandbox_state_transition_hook_default,
[SANDBOX_RUNNING_USER] = sandbox_state_transition_hook_default,
[SANDBOX_ASLEEP] = sandbox_state_transition_hook_default,
[SANDBOX_RETURNED] = sandbox_state_transition_hook_default,
[SANDBOX_COMPLETE] = sandbox_state_transition_hook_default,
[SANDBOX_ERROR] = sandbox_state_transition_hook_default
};
/* Called while nonpreemptable */
sandbox_state_transition_hook_t sandbox_state_transition_from_hooks[SANDBOX_STATE_COUNT] = {
[SANDBOX_UNINITIALIZED] = sandbox_state_transition_hook_default,
[SANDBOX_ALLOCATED] = sandbox_state_transition_hook_default,
[SANDBOX_INITIALIZED] = sandbox_state_transition_hook_default,
[SANDBOX_RUNNABLE] = sandbox_state_transition_hook_default,
[SANDBOX_INTERRUPTED] = sandbox_state_transition_hook_default,
[SANDBOX_PREEMPTED] = sandbox_state_transition_hook_default,
[SANDBOX_RUNNING_SYS] = sandbox_state_transition_hook_default,
[SANDBOX_RUNNING_USER] = sandbox_state_transition_hook_default,
[SANDBOX_ASLEEP] = sandbox_state_transition_hook_default,
[SANDBOX_RETURNED] = sandbox_state_transition_hook_default,
[SANDBOX_COMPLETE] = sandbox_state_transition_hook_default,
[SANDBOX_ERROR] = sandbox_state_transition_hook_default};
[SANDBOX_UNINITIALIZED] = sandbox_state_transition_hook_default,
[SANDBOX_ALLOCATED] = sandbox_state_transition_hook_default,
[SANDBOX_INITIALIZED] = sandbox_state_transition_hook_default,
[SANDBOX_RUNNABLE] = sandbox_state_transition_hook_default,
[SANDBOX_INTERRUPTED] = sandbox_state_transition_hook_default,
[SANDBOX_PREEMPTED] = sandbox_state_transition_hook_default,
[SANDBOX_RUNNING_SYS] = sandbox_state_transition_hook_default,
[SANDBOX_RUNNING_USER] = sandbox_state_transition_hook_default,
[SANDBOX_ASLEEP] = sandbox_state_transition_hook_default,
[SANDBOX_RETURNED] = sandbox_state_transition_hook_default,
[SANDBOX_COMPLETE] = sandbox_state_transition_hook_default,
[SANDBOX_ERROR] = sandbox_state_transition_hook_default
};

@ -1,11 +1,11 @@
#include "sledge_abi.h"
#include "current_sandbox.h"
#include "map.h"
#include "sandbox_set_as_running_sys.h"
#include "sandbox_set_as_running_user.h"
#include "sledge_abi.h"
#include "wasm_memory.h"
#include "wasi.h"
#include "wasi_serdes.h"
#include "wasm_memory.h"
EXPORT void
sledge_abi__wasm_trap_raise(enum sledge_abi__wasm_trap trapno)

@ -1,14 +1,15 @@
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <sys/time.h>
#include <string.h>
#include <stdatomic.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <threads.h>
#include <ucontext.h>
#include <unistd.h>
#include <ucontext.h>
#include <inttypes.h>
#include "arch/context.h"
#include "current_sandbox.h"
@ -18,13 +19,16 @@
#include "module.h"
#include "panic.h"
#include "runtime.h"
#include "sandbox_set_as_interrupted.h"
#include "sandbox_set_as_running_user.h"
#include "sandbox_set_as_interrupted.h"
#include "sandbox_types.h"
#include "scheduler.h"
#include "software_interrupt.h"
#include "software_interrupt_counts.h"
extern uint64_t total_held[1024];
extern uint64_t longest_held[1024];
extern thread_local bool pthread_stop;
thread_local _Atomic volatile sig_atomic_t handler_depth = 0;
thread_local _Atomic volatile sig_atomic_t deferred_sigalrm = 0;
@ -33,7 +37,14 @@ thread_local _Atomic volatile sig_atomic_t deferred_sigalrm = 0;
**************************************/
extern pthread_t *runtime_worker_threads;
extern time_t t_start;
extern pthread_t listener_thread_id;
extern thread_local uint32_t total_local_requests;
extern thread_local int worker_thread_idx;
#ifdef SANDBOX_STATE_TOTALS
extern _Atomic uint32_t sandbox_state_totals[SANDBOX_STATE_COUNT];
#endif
/**************************
* Private Static Inlines *
*************************/
@ -75,6 +86,32 @@ propagate_sigalrm(siginfo_t *signal_info)
}
}
/**
* A POSIX signal is delivered to only one thread.
* This function broadcasts the sigint signal to all other worker threads
*/
static inline void
sigint_propagate_workers_listener(siginfo_t *signal_info)
{
/* Signal was sent directly by the kernel user space, so forward to other threads */
if (signal_info->si_code == SI_KERNEL || signal_info->si_code == SI_USER) {
for (int i = 0; i < runtime_worker_threads_count; i++) {
if (pthread_self() == runtime_worker_threads[i]) continue;
/* All threads should have been initialized */
assert(runtime_worker_threads[i] != 0);
pthread_kill(runtime_worker_threads[i], SIGINT);
}
/* send to listener thread */
if (pthread_self() != listener_thread_id) {
pthread_kill(listener_thread_id, SIGINT);
}
} else {
/* Signal forwarded from another thread. Just confirm it resulted from pthread_kill */
assert(signal_info->si_code == SI_TKILL);
}
}
static inline bool
worker_thread_is_running_cooperative_scheduler(void)
{
@ -184,17 +221,31 @@ software_interrupt_handle_signals(int signal_type, siginfo_t *signal_info, void
break;
}
case SIGINT: {
/* Stop the alarm timer first */
software_interrupt_disarm_timer();
sigint_propagate_workers_listener(signal_info);
/* calculate the throughput */
time_t t_end = time(NULL);
double seconds = difftime(t_end, t_start);
//double throughput = atomic_load(&sandbox_state_totals[SANDBOX_COMPLETE]) / seconds;
double throughput = total_local_requests / seconds;
uint32_t total_sandboxes_error = atomic_load(&sandbox_state_totals[SANDBOX_ERROR]);
printf("throughput is %f error request is %u global total request %d worker %d total requests is %u worker total_held %"PRIu64" longest_held %"PRIu64" listener total_held %"PRIu64" longest_held %"PRIu64"\n", throughput, total_sandboxes_error, atomic_load(&sandbox_state_totals[SANDBOX_COMPLETE]), worker_thread_idx, total_local_requests, total_held[worker_thread_idx], longest_held[worker_thread_idx], total_held[200], longest_held[200]);
fflush(stdout);
pthread_stop = true;
}
default: {
const char *signal_name = strsignal(signal_type);
switch (signal_info->si_code) {
case SI_TKILL:
panic("software_interrupt_handle_signals unexpectedly received signal %s from a thread kill\n",
printf("software_interrupt_handle_signals unexpectedly received signal %s from a thread kill\n",
signal_name);
case SI_KERNEL:
panic("software_interrupt_handle_signals unexpectedly received signal %s from the kernel\n",
printf("software_interrupt_handle_signals unexpectedly received signal %s from the kernel\n",
signal_name);
default:
panic("software_interrupt_handle_signals unexpectedly received signal %s with si_code %d\n",
printf("software_interrupt_handle_signals unexpectedly received signal %s with si_code %d\n",
signal_name, signal_info->si_code);
}
}
@ -268,9 +319,10 @@ software_interrupt_initialize(void)
sigaddset(&signal_action.sa_mask, SIGUSR1);
sigaddset(&signal_action.sa_mask, SIGFPE);
sigaddset(&signal_action.sa_mask, SIGSEGV);
sigaddset(&signal_action.sa_mask, SIGINT);
const int supported_signals[] = {SIGALRM, SIGUSR1, SIGFPE, SIGSEGV};
const size_t supported_signals_len = 4;
const int supported_signals[] = { SIGALRM, SIGUSR1, SIGFPE, SIGSEGV, SIGINT };
const size_t supported_signals_len = 5;
for (int i = 0; i < supported_signals_len; i++) {
int signal = supported_signals[i];

@ -1,5 +1,4 @@
#include "tenant.h"
#include "current_sandbox.h"
#include "tenant_functions.h"
/**
@ -24,50 +23,3 @@ err:
rc = -1;
goto done;
}
#ifdef EXECUTION_REGRESSION
void
tenant_preprocess(struct http_session *session)
{
/* No tenant preprocessing if the wasm module not provided by the tenant */
if (session->route->module_proprocess == NULL) goto done;
const uint64_t start = __getcycles();
/* Tenant Pre-processing - Extract other useful parameters */
struct sandbox *pre_sandbox = sandbox_alloc(session->route->module_proprocess, session, session->route,
session->tenant, 1);
if (sandbox_prepare_execution_environment(pre_sandbox)) panic("pre_sandbox environment setup failed");
pre_sandbox->state = SANDBOX_RUNNING_SYS;
assert(current_sandbox_get() == NULL);
current_sandbox_set(pre_sandbox);
current_sandbox_start();
auto_buf_flush(&session->response_body);
char *endptr;
long num = strtol(session->response_body.data, &endptr, 10);
if (endptr == session->response_body.data) {
printf("No digits were found\n");
} else if (*endptr != '\0' && *endptr != '\n') {
printf("Further characters after number: %s\n", endptr);
} else if ((errno == ERANGE && (num == LONG_MAX || num == LONG_MIN)) || (errno != 0 && num == 0)) {
perror("strtol");
} else {
session->regression_param = num;
}
session->http_request.cursor = 0;
pre_sandbox->http = NULL;
pre_sandbox->state = SANDBOX_COMPLETE;
auto_buf_deinit(&session->response_body);
current_sandbox_set(NULL);
sandbox_free_linear_memory(pre_sandbox);
sandbox_free(pre_sandbox);
const uint64_t end = __getcycles();
session->preprocessing_duration = end - start;
done:
session->did_preprocessing = true;
}
#endif

@ -1,14 +1,14 @@
#include <errno.h>
#include "panic.h"
#include "runtime.h"
#include "tenant.h"
#include "panic.h"
/*******************
* Tenant Database *
******************/
struct tenant *tenant_database[RUNTIME_MAX_TENANT_COUNT] = {NULL};
struct tenant *tenant_database[RUNTIME_MAX_TENANT_COUNT] = { NULL };
size_t tenant_database_count = 0;
/**

@ -1,8 +1,8 @@
#include <assert.h>
#include <errno.h>
#include <pthread.h>
#include <sched.h>
#include <signal.h>
#include <sched.h>
#include <stdlib.h>
#include <threads.h>
@ -12,12 +12,13 @@
#include "local_runqueue_list.h"
#include "local_runqueue_minheap.h"
#include "panic.h"
#include "priority_queue.h"
#include "runtime.h"
#include "scheduler.h"
#include "tenant_functions.h"
#include "worker_thread.h"
#include "tenant_functions.h"
#include "priority_queue.h"
extern thread_local int thread_id;
/***************************
* Worker Thread State *
**************************/
@ -28,6 +29,8 @@ thread_local struct arch_context worker_thread_base_context;
/* Used to index into global arguments and deadlines arrays */
thread_local int worker_thread_idx;
thread_local bool pthread_stop = false;
/* Used to track tenants' timeouts */
thread_local struct priority_queue *worker_thread_timeout_queue;
/***********************
@ -47,6 +50,7 @@ worker_thread_main(void *argument)
/* Index was passed via argument */
worker_thread_idx = *(int *)argument;
thread_id = worker_thread_idx;
/* Set my priority */
// runtime_set_pthread_prio(pthread_self(), 2);
@ -65,6 +69,9 @@ worker_thread_main(void *argument)
software_interrupt_unmask_signal(SIGFPE);
software_interrupt_unmask_signal(SIGSEGV);
/* Unmask SIGINT signals */
software_interrupt_unmask_signal(SIGINT);
/* Unmask signals, unless the runtime has disabled preemption */
if (runtime_preemption_enabled) {
software_interrupt_unmask_signal(SIGALRM);

@ -9,6 +9,7 @@
PHONY: gocr__by_dpi
gocr__by_dpi: ./runtime/bin/gocr.wasm.so
# cd ./tests/gocr/by_dpi && ./install.sh
cd ./tests/gocr/by_dpi && ./run.sh
PHONY: gocr__by_font

1
tests/.gitignore vendored

@ -1,5 +1,4 @@
res
res-*
perf.data
perf.data.old
samples

@ -14,13 +14,13 @@ debug:
.PHONY: client
client:
@curl -H 'Expect:' -H "Content-Type: image/bmp" --data-binary "@../../../applications/wasm_apps/CMSIS_5_NN/images/bmp/airplane1.bmp" "localhost:10000/rand"
@curl -H 'Expect:' -H "Content-Type: image/bmp" --data-binary "@../../../applications/wasm_apps/CMSIS_5_NN/images/bmp/automobile1.bmp" "localhost:10000/rand"
@curl -H 'Expect:' -H "Content-Type: image/bmp" --data-binary "@../../../applications/wasm_apps/CMSIS_5_NN/images/bmp/bird1.bmp" "localhost:10000/rand"
@curl -H 'Expect:' -H "Content-Type: image/bmp" --data-binary "@../../../applications/wasm_apps/CMSIS_5_NN/images/bmp/cat1.bmp" "localhost:10000/rand"
@curl -H 'Expect:' -H "Content-Type: image/bmp" --data-binary "@../../../applications/wasm_apps/CMSIS_5_NN/images/bmp/deer1.bmp" "localhost:10000/rand"
@curl -H 'Expect:' -H "Content-Type: image/bmp" --data-binary "@../../../applications/wasm_apps/CMSIS_5_NN/images/bmp/dog1.bmp" "localhost:10000/rand"
@curl -H 'Expect:' -H "Content-Type: image/bmp" --data-binary "@../../../applications/wasm_apps/CMSIS_5_NN/images/bmp/frog1.bmp" "localhost:10000/rand"
@curl -H 'Expect:' -H "Content-Type: image/bmp" --data-binary "@../../../applications/wasm_apps/CMSIS_5_NN/images/bmp/horse1.bmp" "localhost:10000/rand"
@curl -H 'Expect:' -H "Content-Type: image/bmp" --data-binary "@../../../applications/wasm_apps/CMSIS_5_NN/images/bmp/ship1.bmp" "localhost:10000/rand"
@curl -H 'Expect:' -H "Content-Type: image/bmp" --data-binary "@../../../applications/wasm_apps/CMSIS_5_NN/images/bmp/truck1.bmp" "localhost:10000/rand"
@curl -H 'Expect:' -H "Content-Type: text/plain" --data-binary "@../../../applications/wasm_apps/CMSIS_5_NN/images/bmp/airplane1.bmp" "localhost:10000/rand"
@curl -H 'Expect:' -H "Content-Type: text/plain" --data-binary "@../../../applications/wasm_apps/CMSIS_5_NN/images/bmp/automobile1.bmp" "localhost:10000/rand"
@curl -H 'Expect:' -H "Content-Type: text/plain" --data-binary "@../../../applications/wasm_apps/CMSIS_5_NN/images/bmp/bird1.bmp" "localhost:10000/rand"
@curl -H 'Expect:' -H "Content-Type: text/plain" --data-binary "@../../../applications/wasm_apps/CMSIS_5_NN/images/bmp/cat1.bmp" "localhost:10000/rand"
@curl -H 'Expect:' -H "Content-Type: text/plain" --data-binary "@../../../applications/wasm_apps/CMSIS_5_NN/images/bmp/deer1.bmp" "localhost:10000/rand"
@curl -H 'Expect:' -H "Content-Type: text/plain" --data-binary "@../../../applications/wasm_apps/CMSIS_5_NN/images/bmp/dog1.bmp" "localhost:10000/rand"
@curl -H 'Expect:' -H "Content-Type: text/plain" --data-binary "@../../../applications/wasm_apps/CMSIS_5_NN/images/bmp/frog1.bmp" "localhost:10000/rand"
@curl -H 'Expect:' -H "Content-Type: text/plain" --data-binary "@../../../applications/wasm_apps/CMSIS_5_NN/images/bmp/horse1.bmp" "localhost:10000/rand"
@curl -H 'Expect:' -H "Content-Type: text/plain" --data-binary "@../../../applications/wasm_apps/CMSIS_5_NN/images/bmp/ship1.bmp" "localhost:10000/rand"
@curl -H 'Expect:' -H "Content-Type: text/plain" --data-binary "@../../../applications/wasm_apps/CMSIS_5_NN/images/bmp/truck1.bmp" "localhost:10000/rand"

@ -63,7 +63,7 @@ run_perf_tests() {
else
image=$same_image
fi
hey -disable-compression -disable-keepalive -disable-redirects -n $batch_size -c 1 -cpus 1 -t 0 -o csv -m POST -D "${image}" "http://${hostname}:10000${route[$workload]}" > "$results_directory/${workload}_${batch_id}.csv" 2> /dev/null &
hey -disable-compression -disable-keepalive -disable-redirects -n $batch_size -c 1 -cpus 1 -t 0 -o csv -m GET -D "${image}" "http://${hostname}:10000${route[$workload]}" > "$results_directory/${workload}_${batch_id}.csv" 2> /dev/null &
done
pids=$(pgrep hey | tr '\n' ' ')
[[ -n $pids ]] && wait -f $pids

@ -2,6 +2,8 @@
{
"name": "gwu",
"port": 10000,
"replenishment-period-us": 0,
"max-budget-us": 0,
"routes": [
{
"route": "/rand",

@ -68,7 +68,7 @@ run_perf_tests() {
done
((batch_id++))
hey -disable-compression -disable-keepalive -disable-redirects -n $batch_size -c 1 -cpus 1 -t 0 -o csv -m POST -D "./${workload}.dat" "http://${hostname}:10000${path[$workload]}" > "$results_directory/${workload}_${batch_id}.csv" &
hey -disable-compression -disable-keepalive -disable-redirects -n $batch_size -c 1 -cpus 1 -t 0 -o csv -m GET -D "./${workload}.dat" "http://${hostname}:10000${path[$workload]}" > "$results_directory/${workload}_${batch_id}.csv" &
done
pids=$(pgrep hey | tr '\n' ' ')
[[ -n $pids ]] && wait -f $pids

@ -2,6 +2,8 @@
{
"name": "gwu",
"port": 10000,
"replenishment-period-us": 0,
"max-budget-us": 0,
"routes": [
{
"route": "/ekf_first_iter",

@ -2,6 +2,8 @@
{
"name": "gwu",
"port": 10000,
"replenishment-period-us": 0,
"max-budget-us": 0,
"routes": [
{
"route": "/ekf",

@ -1,21 +1,12 @@
# shellcheck shell=bash
# shellcheck disable=SC2034,SC2153,SC2154,SC2155
# shellcheck disable=SC2034
if [ -n "$__experiment_server_globals_sh__" ]; then return; fi
__experiment_server_globals_sh__=$(date)
# App WASM so files:
declare -r FIBONACCI="fibonacci.wasm.so"
declare -r EKF="gps_ekf.wasm.so"
declare -r CIFAR10="cifar10.wasm.so"
declare -r GOCR="gocr.wasm.so"
declare -r LPD="license_plate_detection.wasm.so"
declare -r RESIZE="resize_image.wasm.so"
declare -r CNN="cnn_face_detection.wasm.so"
# The global configs for the scripts
declare -gr SERVER_LOG_FILE="perf.log"
declare -gr SERVER_HTTP_LOG_FILE="http_perf.log"
declare -gr HEY_OPTS="-disable-compression -disable-keepalive -disable-redirects"
declare -gr NWORKERS=$(($(nproc)-2))
# Sandbox Perf Log Globals:
declare -ga SANDBOX_METRICS=(total queued uninitialized allocated initialized runnable interrupted preempted running_sys running_user asleep returned complete error)
@ -39,18 +30,50 @@ declare -gr SANDBOX_TENANT_NAME_FIELD=2
declare -gr SANDBOX_ROUTE_FIELD=3
declare -gr SANDBOX_CPU_FREQ_FIELD=20
declare -gr SANDBOX_RESPONSE_CODE_FIELD=21
declare -gr SANDBOX_GUARANTEE_TYPE_FIELD=22
# declare -gr SANDBOX_PAYLOAD_SIZE=23
# declare -gr SANDBOX_REGRESSION_PARAM=24
# HTTP Session Perf Log Globals:
declare -ga HTTP_METRICS=(http_receive http_sent http_total http_preprocess)
declare -ga HTTP_METRICS=(http_receive http_sent http_total)
declare -gA HTTP_METRICS_FIELDS=(
[http_receive]=6
[http_sent]=7
[http_total]=8
[http_preprocess]=9
)
declare -gr HTTP_TENANT_NAME_FIELD=1
declare -gr HTTP_ROUTE_FIELD=2
declare -gr HTTP_CPU_FREQ_FIELD=10
declare -gr HTTP_CPU_FREQ_FIELD=9
assert_run_experiments_args() {
if (($# != 3)); then
panic "invalid number of arguments \"$#\""
return 1
elif [[ -z "$1" ]]; then
panic "hostname \"$1\" was empty"
return 1
elif [[ ! -d "$2" ]]; then
panic "directory \"$2\" does not exist"
return 1
elif [[ -z "$3" ]]; then
panic "load gen \"$3\" was empty"
return 1
fi
}
assert_process_client_results_args() {
if (($# != 1)); then
error_msg "invalid number of arguments ($#, expected 1)"
return 1
elif ! [[ -d "$1" ]]; then
error_msg "directory $1 does not exist"
return 1
fi
}
assert_process_server_results_args() {
if (($# != 1)); then
panic "invalid number of arguments \"$#\""
return 1
elif [[ ! -d "$1" ]]; then
panic "directory \"$1\" does not exist"
return 1
fi
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save