Compare commits

..

1 Commits

Author SHA1 Message Date
Sean McBride 07cba9d371 feat: madvise hugepage
4 years ago

@ -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
@ -65,4 +67,4 @@ UseTab: ForIndentation
PenaltyBreakAssignment: 100
PenaltyBreakBeforeFirstCallParameter: 1000
PenaltyReturnTypeOnItsOwnLine: 0
PenaltyReturnTypeOnItsOwnLine: 0

@ -24,6 +24,6 @@
],
"workspaceMount": "source=${localWorkspaceFolder},target=/sledge,type=bind,consistency=cached",
"workspaceFolder": "/sledge",
"postCreateCommand": "make -C /sledge install && make -B -C /sledge/applications clean all",
"postCreateCommand": "make -C /sledge install && make -B -C /sledge/runtime/tests clean all",
"containerUser": "dev",
}

@ -1,12 +1,6 @@
# top-most EditorConfig file
root = true
[.clang-format]
ignore = true
[*.yaml]
ignore = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf

@ -3,9 +3,9 @@ name: sledge
on: [push, pull_request]
env:
LLVM_VERSION: 13
WASI_SDK_VERSION: 12
WASI_SDK_PATH: /opt/wasi-sdk
LLVM_VERSION: 8
WASMCEPTION_URL: https://github.com/gwsystems/wasmception/releases/download/v0.2.0/wasmception-linux-x86_64-0.2.0.tar.gz
# WASI_SDK: /opt/wasi-sdk
LANG: C.UTF-8
LANGUAGE: C.UTF-8
LC_ALL: C.UTF-8
@ -13,18 +13,19 @@ 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 clang-format-11
run: |
sudo ./install_llvm.sh $LLVM_VERSION
- name: Run Clang Format
sudo apt-get remove -y --no-install-recommends clang-format-10 && sudo apt-get install -y --no-install-recommends clang-format-11
- name: Update alternatives
run: |
sudo update-alternatives --remove-all clang-format && sudo update-alternatives --install /usr/bin/clang-format clang-format "/usr/bin/clang-format-11" 100
- 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
@ -60,12 +61,10 @@ jobs:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | \
sh -s -- --default-toolchain stable --component rustfmt --target wasm32-wasi -y
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
# - name: Get WASI-SDK
# run: |
# curl -sS -L -O https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-8/wasi-sdk_8.0_amd64.deb && sudo dpkg -i wasi-sdk_8.0_amd64.deb && rm -f wasi-sdk_8.0_amd64.deb
# echo "ENV WASI_SDK=/opt/wasi-sdk" >> $GITHUB_ENV
- name: Install Test Script Utilities
run: |
sudo apt-get install -y --no-install-recommends \
@ -73,7 +72,6 @@ jobs:
fonts-cascadia-code \
fonts-roboto \
gnuplot \
httpie \
imagemagick \
netpbm \
pango1.0-tools \
@ -86,107 +84,97 @@ jobs:
~/.cargo/git
./awsm/target
key: ${{ runner.os }}-cargo-${{ hashFiles('./awsm/Cargo.lock') }}
- name: Compile aWsm
run: |
make awsm
- name: Compile libsledge
run: |
make libsledge
- name: Compile SLEdge
run: |
make runtime
- name: Install wasm_apps link
run: |
make wasm_apps
- name: Compile sledge
run: |
make build
make rtinit
mkdir bin
mkdir lib
SYS_PREFIX="$(pwd)" ./install.sh
PATH="$(pwd)/bin:$PATH"
echo "$PATH" >> $GITHUB_PATH
LD_LIBRARY_PATH="$(pwd)/lib:$LD_LIBRARY_PATH"
echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" >> $GITHUB_ENV
make build-validate
# TODO:Cache assets before being copied to ./runtime/bin
- name: Cache gocr
uses: actions/cache@v2
with:
path: ./runtime/bin/gocr.wasm.so
key: ${{ runner.os }}-gocr2-${{ hashFiles('./applications/Makefile', './applications/wasm_apps/gocr/**', './libsledge/Makefile' , './libsledge/src/**', './libsledge/include/**') }}
path: ./runtime/bin/gocr_wasm.so
key: ${{ runner.os }}-gocr2-${{ hashFiles('./runtime/tests/gocr/**', './runtime/compiletime/**') }}
if: success() || failure()
- name: Hyde
run: |
echo $WASI_SDK_PATH
ls $WASI_SDK_PATH
make -f test.mk gocr__hyde
./test.sh ocr_hyde
if: success() || failure()
- name: Upload Hyde Logs on Failure
uses: actions/upload-artifact@v2
if: failure()
with:
name: hyde-logs
path: ./tests/gocr/hyde/res/**/
path: ./runtime/experiments/applications/ocr/hyde/res/**/
- name: Handwriting
run: |
make -f test.mk gocr__handwriting
./test.sh ocr_handwriting
if: success() || failure()
- name: Five by Eight
run: |
make -f test.mk gocr__fivebyeight
./test.sh ocr_fivebyeight
if: success() || failure()
# - name: OCR by Word
# run: |
# make -f test.mk gocr__by_word
# ./test.sh ocr_by_word
# if: success() || failure()
# - name: OCR by Font
# run: |
# make -f test.mk gocr__by_font
# ./test.sh ocr_by_font
# if: success() || failure()
# - name: OCR by DPI
# run: |
# make -f test.mk gocr__by_dpi
# ./test.sh ocr_by_dpi
# if: success() || failure()
# TODO:Cache assets before being copied to ./runtime/bin
- name: Cache EKF
uses: actions/cache@v2
with:
path: ./runtime/bin/gps_ekf.wasm.so
key: ${{ runner.os }}-gocr2-${{ hashFiles('./applications/Makefile', './applications/wasm_apps/TinyEKF/**', './libsledge/Makefile' , './libsledge/src/**', './libsledge/include/**') }}
path: ./runtime/bin/ekf_wasm.so
key: ${{ runner.os }}-gocr2-${{ hashFiles('./runtime/tests/TinyEKF/**', './runtime/compiletime/**') }}
if: success() || failure()
- name: EKF one iteration
run: |
make -f test.mk ekf__one_iteration
./test.sh ekf_one_iteration
if: success() || failure()
# - name: EKF by Iteration
# run: |
# make -f test.mk ekf__by_iteration
# ./test.sh ekf_by_iteration
# if: success() || failure()
# TODO:Cache assets before being copied to ./runtime/bin
- name: Image Classification
run: |
make -f test.mk cifar10__image_classification
./test.sh image_classification
if: success() || failure()
# TODO:Cache assets before being copied to ./runtime/bin
- name: Image Resize
run: |
make -f test.mk sod__image_resize__test
./test.sh image_resize
if: success() || failure()
# - name: Image Resize by Resolution
# run: |
# make -f test.mk sod__image_resize__by_resolution
# ./test.sh image_resize_by_resolution
# if: success() || failure()
# - name: License Plate Detection by Plate Count
# run: |
# make -f test.mk sod__lpd_by_plate_count
# ./test.sh lpd_by_plate_count
# if: success() || failure()
# - name: Bimodal
# run: |
# make -f test.mk fibonacci__bimodal
# ./test.sh bimodal
# if: success() || failure()
# - name: Concurrency
# run: |
# make -f test.mk empty__concurrency
# ./test.sh concurrency
# if: success() || failure()
# - name: Payload
# run: |
# make -f test.mk TODO
# ./test.sh payload
# if: success() || failure()
- name: Wasm Trap Divide by Zero
run: |
make -f test.mk trap_divzero
if: success() || failure()
- name: Wasm Trap Stack Overflow
run: |
make -f test.mk stack_overflow
if: success() || failure()

9
.gitignore vendored

@ -52,11 +52,10 @@ dkms.conf
runtime/tags
runtime/bin
applications/wasm_apps
applications/tmp/
applications/**/*.csv
applications/**/*.txt
applications/**/*.xlsx
runtime/tests/tmp/
runtime/tests/**/*.csv
runtime/tests/**/*.txt
runtime/tests/**/*.xlsx
# Swap Files
*.swp

39
.gitmodules vendored

@ -1,14 +1,33 @@
[submodule "awsm"]
path = awsm
url = https://github.com/gwsystems/aWsm
ignore = dirty
branch = master
path = awsm
url = https://github.com/gwsystems/aWsm
ignore = dirty
[submodule "http-parser"]
path = runtime/thirdparty/http-parser
url = https://github.com/gwsystems/http-parser.git
path = runtime/thirdparty/http-parser
url = https://github.com/gwsystems/http-parser.git
[submodule "ck"]
path = runtime/thirdparty/ck
url = https://github.com/gwsystems/ck.git
path = runtime/thirdparty/ck
url = https://github.com/gwsystems/ck.git
[submodule "jsmn"]
path = runtime/thirdparty/jsmn
url = https://github.com/gwsystems/jsmn.git
path = runtime/thirdparty/jsmn
url = https://github.com/gwsystems/jsmn.git
[submodule "runtime/tests/gocr"]
path = runtime/tests/gocr
url = https://github.com/gwsystems/gocr.git
branch = sledge
[submodule "runtime/tests/TinyEKF"]
path = runtime/tests/TinyEKF
url = https://github.com/gwsystems/TinyEKF.git
branch = sledge
[submodule "runtime/tests/CMSIS_5_NN"]
path = runtime/tests/CMSIS_5_NN
url = https://github.com/gwsystems/CMSIS_5_NN.git
branch = sledge
[submodule "runtime/tests/sod"]
path = runtime/tests/sod
url = https://github.com/gwsystems/sod.git
branch = sledge
[submodule "runtime/tests/speechtotext"]
path = runtime/tests/speechtotext
url = https://github.com/gwsystems/speechtotext.git
branch = sledge

@ -1,23 +1,22 @@
{
"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/"
],
"defines": [
"x86_64",
"_GNU_SOURCE"
],
"cStandard": "c17",
"compilerPath": "/usr/bin/clang"
}
],
"version": 4
}

@ -80,7 +80,9 @@
"sandbox_set_as_runnable.h": "c",
"sandbox_set_as_complete.h": "c",
"deque.h": "c",
"sandbox_request.h": "c",
"sandbox_send_response.h": "c",
"sandbox_setup_arguments.h": "c",
"worker_thread.h": "c",
"sandbox_set_as_error.h": "c",
"likely.h": "c",
@ -89,9 +91,6 @@
"sandbox_set_as_running.h": "c",
"sandbox_summarize_page_allocations.h": "c",
"wasm_types.h": "c",
"wasi_impl.h": "c",
"wasi_backing.h": "c",
"wasi_serdes.h": "c",
"atomic": "c",
"sandbox_set_as_running_kernel.h": "c",
"stdbool.h": "c",
@ -100,64 +99,7 @@
"sandbox_state_history.h": "c",
"sandbox_set_as_running_user.h": "c",
"scheduler.h": "c",
"sandbox_set_as_returned.h": "c",
"software_interrupt_counts.h": "c",
"sandbox_set_as_running_sys.h": "c",
"wasm_module_instance.h": "c",
"wasm_stack.h": "c",
"wasm_table.h": "c",
"wasi_spec.h": "c",
"current_wasm_module_instance.h": "c",
"wasm_memory.h": "c",
"sledge_abi.h": "c",
"vec.h": "c",
"perf_window_t.h": "c",
"module_config.h": "c",
"tenant.h": "c",
"route_config.h": "c",
"http_router.h": "c",
"execution_histogram.h": "c",
"tcp_server.h": "c",
"stdint.h": "c",
"scheduler_options.h": "c",
"route_config_parse.h": "c",
"route.h": "c",
"pool.h": "c",
"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"
"sandbox_set_as_returned.h": "c"
},
"files.exclude": {
"**/.git": true,
@ -180,12 +122,10 @@
],
"shellformat.path": "/usr/local/bin/shfmt",
"shellformat.flag": "-ln=bash -i 0 -bn -ci -sr -kp",
"terminal.integrated.shell.linux": "bash",
"[jsonc]": {
"editor.defaultFormatter": "vscode.json-language-features"
},
"[yaml]": {
"editor.formatOnSave": false,
},
"[json]": {
"editor.defaultFormatter": "vscode.json-language-features"
},
@ -211,14 +151,5 @@
"*.o": true,
"*.bc": true,
"*.wasm": true,
},
"C_Cpp.formatting": "clangFormat",
"cSpell.words": [
"gregs",
"mctx",
"TKILL",
"WASI"
],
"C_Cpp.errorSquiggles": "Enabled",
"C_Cpp.default.compilerPath": "/usr/bin/clang"
}
}

@ -15,7 +15,6 @@ RUN apt-get install -y --no-install-recommends \
pkg-config \
gcc \
g++ \
httpie \
clang-8 \
clang-tools-8 \
llvm-8 \
@ -50,6 +49,4 @@ RUN rustup target add wasm32-wasi
RUN cargo install --debug cargo-audit cargo-watch rsign2
ENV PATH=/sledge/runtime/bin:$PATH
ENV PATH=/sledge/awsm/target/release:$PATH
ENV LD_LIBRARY_PATH=/sledge/runtime/bin:$LD_LIBRARY_PATH
ENV PATH=/opt/sledge/bin:$PATH

@ -1,14 +1,11 @@
# 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-8/wasi-sdk_8.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
ARG SHELLCHECK_URL=https://github.com/koalaman/shellcheck/releases/download/v0.7.1/shellcheck-v0.7.1.linux.x86_64.tar.xz
# Use bash, not sh
SHELL ["/bin/bash", "-c"]
@ -49,7 +46,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
fonts-cascadia-code \
fonts-roboto \
gnuplot \
httpie \
imagemagick \
jq \
libz3-4 \
@ -77,12 +73,14 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
vim \
wabt
ENV LLVM_VERSION=8
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
ENV WASI_SDK_PATH=/opt/wasi-sdk
# TODO: Refactor to output as an arch-neutral filename
# RUN curl -sS -L -O $WASI_SDK_URL && dpkg -i wasi-sdk_8.0_amd64.deb && rm -f wasi-sdk_8.0_amd64.deb
# ENV WASI_SDK=/opt/wasi-sdk
# Create non-root user and add to sudoers
ARG USERNAME=dev
@ -101,6 +99,8 @@ USER $USER_UID
RUN sudo chown $USER_GID:$USER_GID /sledge
ADD fix_root.sh /sledge/fix_root.sh
RUN cd sledge && ./fix_root.sh
RUN sudo mkdir /opt/sledge
RUN sudo chown $USER_GID:$USER_GID /opt/sledge
################################
# Final Setup as non-root user #
@ -118,6 +118,8 @@ ENV LANGUAGE C.UTF-8
ENV LC_ALL C.UTF-8
# Update PATH and LD_LIBRARY_PATH
ENV PATH=/sledge/runtime/bin:$PATH
ENV PATH=/sledge/awsm/target/release:$PATH
ENV LD_LIBRARY_PATH=/sledge/runtime/bin:$LD_LIBRARY_PATH
ENV PATH=/opt/sledge/bin:$PATH
# TODO: Does the build process for the sample applications actually copy here?
# TODO: Should we create a special SLEDGE_MODULE_PATH that is searched for these modules?
ENV LD_LIBRARY_PATH=/opt/sledge/bin:$LD_LIBRARY_PATH

@ -1,60 +1,54 @@
SHELL:=/bin/bash
.PHONY: all
all: awsm libsledge runtime applications
ARCH:=$(shell arch)
COMPILER=awsm
ROOT=${ROOT:-$(cd "$(dirname ${BASH_SOURCE:-$0})" && pwd)}
WASMCEPTION_URL=https://github.com/gwsystems/wasmception/releases/download/v0.2.0/wasmception-linux-x86_64-0.2.0.tar.gz
# TODO: Add ARM release build
.PHONY: build
build:
ifeq ($(ARCH),x86_64)
cd ./awsm/wasmception && wget ${WASMCEPTION_URL} -O wasmception.tar.gz && tar xvfz wasmception.tar.gz && rm wasmception.tar.gz
endif
test -f ./${COMPILER}/wasmception/dist/bin/clang || make -C ${COMPILER}/wasmception
@cd ${COMPILER} && RUSTUP_TOOLCHAIN=stable cargo build --release && cd ${ROOT}
# Sanity check that the aWsm compiler built and is in our PATH
.PHONY: build-validate
build-validate:
which awsm
awsm --version
.PHONY: build-dev
build-dev:
test -f ./${COMPILER}/wasmception/dist/bin/clang || make -C ${COMPILER}/wasmception
@echo "Building aWsm compiler (default==debug)"
@cd ${COMPILER} && cargo build && cd ${ROOT}
.PHONY: clean
clean: awsm.clean libsledge.clean runtime.clean applications.clean
.PHONY: submodules
submodules:
git submodule update --init --recursive
.PHONY: install
install: submodules wasm_apps all
# aWsm: the WebAssembly to LLVM bitcode compiler
.PHONY: awsm
awsm:
cd awsm && cargo build --release
.PHONY: awsm.clean
awsm.clean:
cd awsm && cargo clean
# libsledge: the support library linked with LLVM bitcode emitted by aWsm when building *.so modules
.PHONY: libsledge
libsledge:
make -C libsledge dist/libsledge.a
clean:
@echo "Cleaning aWsm compiler"
@cd ${COMPILER} && cargo clean && cd ${ROOT}
# wasmception is too slow to recompile,
# so lets not make that part of the "aWsm" cleanup
.PHONY: wclean
wclean:
@echo "Cleaning wasmception toolchain"
@cd ${COMPILER} && make -C wasmception clean && cd ${ROOT}
.PHONY: rtinit
rtinit:
@echo "Building runtime for the first time!"
make -C runtime init
.PHONY: libsledge.clean
libsledge.clean:
make -C libsledge clean
# sledgert: the runtime that executes *.so modules
.PHONY: runtime
runtime:
@echo "Building runtime!"
make -C runtime
.PHONY: install
install: build rtinit
@./install.sh wasmception
.PHONY: runtime.clean
runtime.clean:
make -C runtime clean
# SLEdge Applications
.PHONY: applications
applications:
make -C applications all
.PHONY: applications.clean
applications.clean:
make -C applications clean
# Instead of having two copies of wasm_apps, just link to the awsm repo's copy
wasm_apps:
ln -sr awsm/applications/wasm_apps/ applications/
# Tests
.PHONY: test
test:
make -f test.mk all

@ -2,25 +2,14 @@
**SLEdge** is a lightweight serverless solution suitable for edge computing. It builds on WebAssembly sandboxing provided by the [aWsm compiler](https://github.com/gwsystems/aWsm).
## Setting up a development environment
## Host Dependencies
### Native on Debian Host
- Docker - [Installation Instructions](https://docs.docker.com/install/)
```sh
git clone https://github.com/gwsystems/sledge-serverless-framework.git
cd sledge-serverless-framework
./install_deb.sh
source ~/.bashrc
make install
make test
```
### Docker
## Setting up the environment
**Note: These steps require Docker. Make sure you've got it installed!**
[Docker Installation Instructions](https://docs.docker.com/install/)
We provide a Docker build environment configured with the dependencies and toolchain needed to build the SLEdge runtime and serverless functions.
To setup this environment, run:
@ -29,7 +18,7 @@ To setup this environment, run:
./devenv.sh setup
```
### Using the Docker container to compile your serverless functions
## Using the Docker container to compile your serverless functions
To enter the docker environment, run:
@ -44,10 +33,10 @@ cd /sledge/runtime
make clean all
```
There are a set of benchmarking applications in the `/sledge/applications` directory. Run the following to compile all benchmarks runtime tests using the aWsm compiler and then copy all resulting `<application>.wasm.so` files to /sledge/runtime/bin.
There are a set of benchmarking applications in the `/sledge/runtime/tests` directory. Run the following to compile all benchmarks runtime tests using the aWsm compiler and then copy all resulting `<application>_wasm.so` files to /sledge/runtime/bin.
```bash
cd /sledge/applications/
cd /sledge/runtime/tests/
make clean all
```
@ -65,85 +54,59 @@ To stop the Docker container:
./devenv.sh stop
```
### Deleting Docker Build Containers
If you are finished working with the SLEdge runtime and wish to remove it, run the following command to delete our Docker build and runtime images.
```bash
./devenv.sh rma
```
And then simply delete this repository.
## Running your first serverless function
An SLEdge serverless function consists of a shared library (\*.so) and a JSON configuration file that determines how the runtime should execute the serverless function. As an example, here is the configuration file for our sample fibonacci function:
```json
[
{
"name": "GWU",
"port": 10010,
"routes": [
{
"route": "/fib",
"path": "fibonacci.wasm.so",
"expected-execution-us": 6000,
"relative-deadline-us": 20000,
"http-resp-content-type": "text/plain"
}
]
}
]
{
"name": "fibonacci",
"path": "fibonacci_wasm.so",
"port": 10000,
"expected-execution-us": 600,
"relative-deadline-us": 2000,
"http-req-size": 1024,
"http-resp-size": 1024,
"http-resp-content-type": "text/plain"
}
```
The `port` and `route` fields are used to determine the path where our serverless function will be served served.
The `port` and `name` fields are used to determine the path where our serverless function will be served served.
In our case, we are running the SLEdge runtime on localhost, so our function is available at `localhost:10010/fib`.
In our case, we are running the SLEdge runtime on localhost, so our function is available at `http://localhost:10000/fibonacci`
Our fibonacci function will parse a single argument from the HTTP POST body that we send. The expected Content-Type is "text/plain".
Our fibonacci function will parse a single argument from the HTTP POST body that we send. The expected Content-Type is "text/plain" and the buffer is sized to 1024 bytes for both the request and response. This is sufficient for our simple Fibonacci function, but this must be changed and sized for other functions, such as image processing.
Now that we understand roughly how the SLEdge runtime interacts with serverless function, let's run Fibonacci!
The fastest way to check it out is just to click on the following URL on your Web browser: [http://localhost:10010/fib?10](http://localhost:10010/fib?10)
From the root project directory of the host environment (not the Docker container!), navigate to the binary directory
```bash
cd runtime/bin/
```
Now run the sledgert binary, passing the JSON file of the serverless function we want to serve. Because serverless functions are loaded by SLEdge as shared libraries, we want to add the `applications/` directory to LD_LIBRARY_PATH.
Now run the sledgert binary, passing the JSON file of the serverless function we want to serve. Because serverless functions are loaded by SLEdge as shared libraries, we want to add the `runtime/tests/` directory to LD_LIBRARY_PATH.
```bash
LD_LIBRARY_PATH="$(pwd):$LD_LIBRARY_PATH" ./sledgert ../../tests/fibonacci/bimodal/spec.json
LD_LIBRARY_PATH="$(pwd):$LD_LIBRARY_PATH" ./sledgert ../tests/test_fibonacci.json
```
While you don't see any output to the console, the runtime is running in the foreground.
Let's now invoke our serverless function to compute the 10th fibonacci number. We'll use `cURL` and [HTTPie](https://httpie.org/) to send a HTTP GET and POST requests with the parameter we want to pass to my serverless function. Feel free to use whatever other network client you prefer!
Let's now invoke our serverless function to compute the 10th fibonacci number. I'll use [HTTPie](https://httpie.org/) to send a POST request with a body containing the parameter I want to pass to my serverless function. Feel free to use cURL or whatever network client you prefer!
Open a **new** terminal session and execute the following
Open a new terminal session and execute the following
```bash
# HTTP GET method:
http localhost:10010/fib?10
curl localhost:10010/fib?10
# HTTP POST method:
echo "10" | http POST localhost:10010/fib
curl -i -d 10 localhost:10010/fib
echo "10" | http :10000
```
You should receive the following in response. The serverless function says that the 10th fibonacci number is 55, which seems to be correct!
```bash
HTTP/1.1 200 OK
Server: SLEdge
Connection: close
Content-Type: text/plain
Content-Length: 3
Content-length: 3
Content-type: text/plain
55
```
@ -152,10 +115,18 @@ When done, terminal the SLEdge runtime with `Ctrl+c`
## Running Test Workloads
Various synthetic and real-world tests can be found in `runtime/tests`. Generally, each experiment can be run by Make rules in the top level `test.mk`.
Various synthetic and real-world tests can be found in `runtime/experiments`. Generally, each experiment can be run be executing the `run.sh` script.
## Removing the SLEdge Runtime
If you are finished working with the SLEdge runtime and wish to remove it, run the following command to delete our Docker build and runtime images.
`make -f test.mk all`
```bash
./devenv.sh rma
```
And then simply delete this repository.
## Problems or Feedback?
If you encountered bugs or have feedback, please let us know in our [issue tracker.](https://github.com/gwsystems/sledge-serverless-framework/issues)
If you encountered bugs or have feedback, please let us know in our [issue tracker.](https://github.com/phanikishoreg/awsm-Serverless-Framework/issues)

@ -1 +0,0 @@
dist/*

@ -1,133 +0,0 @@
AWSMCC=../awsm/target/release/awsm
CC=clang
# Used by aWsm when compiling the *.wasm to *.bc
AWSMFLAGS= --inline-constant-globals --runtime-globals
# Used by clang when compiling the *.so module
# --whole-archive causes the symbols in the listed static archive to be exported from the resulting *.so
# https://stackoverflow.com/questions/805555/ld-linker-question-the-whole-archive-option
CFLAGS=-O3 -flto
LDFLAGS=-shared -fPIC -Wl,--export-dynamic,--whole-archive -L../libsledge/dist/ -lsledge -Wl,--no-whole-archive
# LDFLAGS=-flto -fvisibility=hidden
# Strips out calls to assert() and disables debuglog
CFLAGS+=-DNDEBUG
dist:
mkdir -p dist
.PHONY: all
all: \
cifar10.install \
empty.install \
fibonacci.install \
gocr.install \
gps_ekf.install \
license_plate_detection.install \
resize_image.install \
cnn_face_detection.install \
get_jpeg_resolution.install \
.PHONY: clean
clean:
@make -C wasm_apps clean
@rm -rf dist
@rm -rf ../runtime/bin/*.so
wasm_apps/dist/%.wasm:
make -C wasm_apps $(addprefix dist/,$(notdir $@))
../libsledge/dist/:
mkdir ../libsledge/dist
../libsledge/dist/libsledge.a: ../libsledge/dist/
make -C .. libsledge
PHONY: scratch_storage
scratch_storage:
make -C scratch_storage all
PHONY: scratch_storage.install
scratch_storage.install: \
scratch_storage_get.install \
scratch_storage_set.install \
scratch_storage_delete.install \
scratch_storage_upsert.install
scratch_storage/scratch_storage_%.wasm:
make -C scratch_storage all
dist/scratch_storage_%.bc: scratch_storage/scratch_storage_%.wasm dist
${AWSMCC} ${AWSMFLAGS} $< -o $@
dist/%.bc: ./wasm_apps/dist/%.wasm dist
${AWSMCC} ${AWSMFLAGS} $< -o $@
dist/%.ll: dist/%.bc
llvm-dis $< -o $@
dist/%.wasm.so: dist/%.bc
${CC} ${CFLAGS} ${LDFLAGS} $^ -o $@
../runtime/bin/%.wasm.so: dist/%.wasm.so
cp $^ $@
.PHONY: cifar10.install
cifar10.install: ../runtime/bin/cifar10.wasm.so
# Echo?
.PHONY: empty.install
empty.install: ../runtime/bin/empty.wasm.so
.PHONY: exit.install
exit.install: ../runtime/bin/exit.wasm.so
.PHONY: fibonacci.install
fibonacci.install: ../runtime/bin/fibonacci.wasm.so
.PHONY: asc-fib.install
asc-fib.install: ../runtime/bin/asc-fib.wasm.so
.PHONY: gocr.install
gocr.install: ../runtime/bin/gocr.wasm.so
.PHONY: resize_image.install
resize_image.install: ../runtime/bin/resize_image.wasm.so
.PHONY: gps_ekf.install
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
.PHONY: stack_overflow.install
stack_overflow.install: ../runtime/bin/stack_overflow.wasm.so
.PHONY: html.install
html.install: ../runtime/bin/html.wasm.so
.PHONY: scratch_storage_get.install
scratch_storage_get.install: ../runtime/bin/scratch_storage_get.wasm.so
.PHONY: scratch_storage_set.install
scratch_storage_set.install: ../runtime/bin/scratch_storage_set.wasm.so
.PHONY: scratch_storage_delete.install
scratch_storage_delete.install: ../runtime/bin/scratch_storage_delete.wasm.so
.PHONY: scratch_storage_upsert.install
scratch_storage_upsert.install: ../runtime/bin/scratch_storage_upsert.wasm.so
.PHONY: depth_to_xyz.install
depth_to_xyz.install: ../runtime/bin/depth_to_xyz.wasm.so

@ -1,24 +0,0 @@
include ../wasm_apps/common.mk
.PHONY: all
all: \
scratch_storage_get.wasm \
scratch_storage_set.wasm \
scratch_storage_delete.wasm \
scratch_storage_upsert.wasm \
.PHONY: clean
clean:
@rm -f scratch_storage_set.wa* scratch_storage_get.wa* scratch_storage_delete.wa* scratch_storage_upsert.wa*
scratch_storage_set.wasm: scratch_storage_set.c
@${WASMCC} ${WASMCFLAGS} ${WASMLDFLAGS} $^ -o $@
scratch_storage_get.wasm: scratch_storage_get.c
@${WASMCC} ${WASMCFLAGS} ${WASMLDFLAGS} $^ -o $@
scratch_storage_delete.wasm: scratch_storage_delete.c
@${WASMCC} ${WASMCFLAGS} ${WASMLDFLAGS} $^ -o $@
scratch_storage_upsert.wasm: scratch_storage_upsert.c
@${WASMCC} ${WASMCFLAGS} ${WASMLDFLAGS} $^ -o $@

@ -1,32 +0,0 @@
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int scratch_storage_delete(void *key, uint32_t key_len)
__attribute__((__import_module__("scratch_storage"), __import_name__("delete")));
int
main(int argc, char **argv)
{
if (argc < 2) {
fprintf(stderr, "%s <key>", argv[0]);
return 0;
}
char *key = argv[1];
if (key == NULL || strlen(key) < 0) {
fprintf(stderr, "%s <key>", argv[0]);
return 0;
}
int rc = scratch_storage_delete(key, strlen(key));
if (rc == 1) {
printf("Key '%s' not found\n", key);
return 0;
} else {
printf("Key %s deleted\n", key);
}
};

@ -1,38 +0,0 @@
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int scratch_storage_get(void *key, uint32_t key_len, void *buf, uint32_t buf_len)
__attribute__((__import_module__("scratch_storage"), __import_name__("get")));
extern uint32_t scratch_storage_get_size(void *key, uint32_t key_len)
__attribute__((__import_module__("scratch_storage"), __import_name__("get_size")));
int
main(int argc, char **argv)
{
if (argc < 2) {
fprintf(stderr, "%s <key>", argv[0]);
return 0;
}
char *key = argv[1];
if (key == NULL || strlen(key) < 0) {
fprintf(stderr, "%s <key>", argv[0]);
return 0;
}
uint32_t val_size = scratch_storage_get_size(key, strlen(key));
char *buf = calloc(val_size + 1, sizeof(char));
int rc = scratch_storage_get(key, strlen(key), buf, val_size);
assert(rc != 2);
if (rc == 1) {
printf("Key '%s' not found\n", key);
return 0;
} else {
printf("Key %s resolved to value of size %u with contents %s\n", key, val_size, buf);
}
};

@ -1,35 +0,0 @@
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int scratch_storage_set(void *key, uint32_t key_len, void *value, uint32_t value_len)
__attribute__((__import_module__("scratch_storage"), __import_name__("set")));
int
main(int argc, char **argv)
{
if (argc < 3) {
fprintf(stderr, "%s <key> <value>", argv[0]);
return 0;
}
char *key = argv[1];
char *value = argv[2];
if (key == NULL || strlen(key) < 0 || value == NULL || strlen(value) < 0) {
fprintf(stderr, "%s <key> <value>", argv[0]);
return 0;
}
int rc = scratch_storage_set(key, strlen(key), value, strlen(value));
if (rc == 1) {
printf("Key %s was already present\n", key);
return 0;
}
assert(rc == 0);
printf("Key %s set to value %s\n", key, value);
return rc;
};

@ -1,28 +0,0 @@
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int scratch_storage_upsert(void *key, uint32_t key_len, void *value, uint32_t value_len)
__attribute__((__import_module__("scratch_storage"), __import_name__("upsert")));
int
main(int argc, char **argv)
{
if (argc < 3) {
fprintf(stderr, "%s <key> <value>", argv[0]);
return 0;
}
char *key = argv[1];
char *value = argv[2];
if (key == NULL || strlen(key) < 0 || value == NULL || strlen(value) < 0) {
fprintf(stderr, "%s <key> <value>", argv[0]);
return 0;
}
scratch_storage_upsert(key, strlen(key), value, strlen(value));
printf("Key %s set to value %s\n", key, value);
};

@ -1 +1 @@
Subproject commit 272fcf42b6559ccb5c5213eb78edfc0f703520ab
Subproject commit 84ad52b5c307ffdf9dc585bc40ae1122563a6857

@ -136,7 +136,6 @@ envrun() {
echo "Starting ${SYS_DOC_NAME}"
docker run \
--privileged \
--network="host" \
--security-opt seccomp:unconfined \
--name=${SYS_DOC_NAME} \
--detach \

@ -1,59 +0,0 @@
SLEdge only implemented a subset of the WASI syscall interface
## Arguments
The WASI calls `args_sizes_get` and `args_get` are supported. HTTP query parameters are captured and passed as arguments.
## Environment Variables
The WASI calls `environ_get` and `environ_sizes_get` are supported, but mostly unused. The current behavior is to to pass the runtime's environment variables into the sandbox. This is likely undesirable.
Presumably, the runtime should provide a standard set of environment variables and also allow the JSON spec to set additional function-specific environment variables.
See the reference of environment variables generated by WAGI for details: https://github.com/deislabs/wagi/blob/main/docs/environment_variables.md
## Clocks
`clock_time_get` is implemented but untested. `clock_res_get` is unimplemented.
## File System
SLEdge only supports `fd_read` from stdin and `fd_write` to stderr or stdout.
stdin is populated with the body of an HTTP POST request. stdout and stderr are both written in an interleaved fashion into a buffer and sent back to the client as the response body.
Actual access to the file system is unsupported, and sandboxes are not provided any preopened descriptors.
## Poll
`poll_oneoff` is unsupposed because SLEdge serverless functions are short lived. Sandboxed functions are assumed to make blocking reads/writes to stdin/stdout/stderr, and the serverless runtime is responsible for causing serverless functions to sleep and wake.
## Exit
`proc_exit` is supported and causes a sandbox to terminate execution.
## Signals
`proc_raise` is not supported. Signals are used by the runtime to provide preemption and context switching. It would be dangerous to trigger actual host signals from a sandbox.
However, the function could be implemented by creating a switch on the wasi signal and either ignoring or handling the signal within the `proc_raise` function itself.
`SIGABRT` could trigger the sandbox to exit in an abnormal condition.
The default ignore behavior could log the unexpected signal and return.
## Random
`random_get` is supported but largely untested.
## Yield
`sched_yield` is unsupported. This does not match with the run-to-completion nature of serverless.
In the case of EDF, a sandbox would always yield to itself. However, in the case of FIFO, we could enable this call to allow for a worker to "round robin" within a runqueue. However, it is unclear what the rationale would be to allow a serverless function to impact the scheduler.
## Sockets
All socket syscalls are unimplemented because the current logic around `sock_accept` and `sock_shutdown` seems to be focused on long-lived daemon nanoprocesses that handle multiple requests. The `poll_oneoff` call also seems to be based on this usecase.
Generally, a serverless function is expected to only make outbound network requests. However, this use case does not seem to be currently supported by WASI.

@ -1,3 +1 @@
This is a state transition diagram of a sandbox. This maps to the state transition functions defined in `runtime/include/sandbox_set_as_*.h`
Technically, this does not capture all state transitions to or from SANDBOX_INTERRUPTED, as any state can be interrupted by a SIGALRM and this would clutter the diagram. The only transitions shown to or from SANDBOX_INTERRUPTED are those leading to SANDBOX_PREEMPTED, as this reflects actual changes to a sandbox within the scheduler. All other transitions to/from SANDBOX_INTERRUPTED are mostly concerned with preventing scheduler execution time from being counted against sandbox execution times.

@ -2,19 +2,11 @@ digraph {
Uninitialized -> Initialized
Initialized -> {Runnable Error}
Runnable -> Running_Sys
Running_User -> Interrupted [label="interrupt"]
Running_User -> Running_Sys [label="syscall"]
Interrupted -> Preempted [label="preempt"]
Interrupted -> Running_User
Running_User -> Running_Sys [label="interrupt"]
Running_Sys -> Asleep [label="sleep"]
Running_Sys -> {Error Returned}
Running_Sys -> Running_User [label="return"]
Running_Sys -> Preempted [label="preempt"]
Preempted -> Running_User
Returned -> Complete [label="exit_success"]
Asleep -> Runnable [label="wakeup"]

@ -4,173 +4,154 @@
<!-- Generated by graphviz version 2.43.0 (0)
-->
<!-- Title: %3 Pages: 1 -->
<svg width="480pt" height="524pt"
viewBox="0.00 0.00 479.99 524.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 520)">
<svg width="650pt" height="437pt"
viewBox="0.00 0.00 649.79 437.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 433)">
<title>%3</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-520 475.99,-520 475.99,4 -4,4"/>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-433 645.79,-433 645.79,4 -4,4"/>
<!-- Uninitialized -->
<g id="node1" class="node">
<title>Uninitialized</title>
<ellipse fill="none" stroke="black" cx="344.6" cy="-498" rx="70.39" ry="18"/>
<text text-anchor="middle" x="344.6" y="-494.3" font-family="Times,serif" font-size="14.00">Uninitialized</text>
<ellipse fill="none" stroke="black" cx="70.19" cy="-411" rx="70.39" ry="18"/>
<text text-anchor="middle" x="70.19" y="-407.3" font-family="Times,serif" font-size="14.00">Uninitialized</text>
</g>
<!-- Initialized -->
<g id="node2" class="node">
<title>Initialized</title>
<ellipse fill="none" stroke="black" cx="344.6" cy="-425" rx="57.39" ry="18"/>
<text text-anchor="middle" x="344.6" y="-421.3" font-family="Times,serif" font-size="14.00">Initialized</text>
<ellipse fill="none" stroke="black" cx="70.19" cy="-338" rx="57.39" ry="18"/>
<text text-anchor="middle" x="70.19" y="-334.3" font-family="Times,serif" font-size="14.00">Initialized</text>
</g>
<!-- Uninitialized&#45;&gt;Initialized -->
<g id="edge1" class="edge">
<title>Uninitialized&#45;&gt;Initialized</title>
<path fill="none" stroke="black" d="M344.6,-479.81C344.6,-471.79 344.6,-462.05 344.6,-453.07"/>
<polygon fill="black" stroke="black" points="348.1,-453.03 344.6,-443.03 341.1,-453.03 348.1,-453.03"/>
<path fill="none" stroke="black" d="M70.19,-392.81C70.19,-384.79 70.19,-375.05 70.19,-366.07"/>
<polygon fill="black" stroke="black" points="73.69,-366.03 70.19,-356.03 66.69,-366.03 73.69,-366.03"/>
</g>
<!-- Runnable -->
<g id="node3" class="node">
<title>Runnable</title>
<ellipse fill="none" stroke="black" cx="232.6" cy="-352" rx="54.69" ry="18"/>
<text text-anchor="middle" x="232.6" y="-348.3" font-family="Times,serif" font-size="14.00">Runnable</text>
<ellipse fill="none" stroke="black" cx="266.19" cy="-265" rx="54.69" ry="18"/>
<text text-anchor="middle" x="266.19" y="-261.3" font-family="Times,serif" font-size="14.00">Runnable</text>
</g>
<!-- Initialized&#45;&gt;Runnable -->
<g id="edge2" class="edge">
<title>Initialized&#45;&gt;Runnable</title>
<path fill="none" stroke="black" d="M320.29,-408.59C304.3,-398.45 283.15,-385.05 265.63,-373.94"/>
<polygon fill="black" stroke="black" points="267.17,-370.77 256.85,-368.38 263.42,-376.69 267.17,-370.77"/>
<path fill="none" stroke="black" d="M106.14,-323.98C138.57,-312.23 186.39,-294.91 221.32,-282.26"/>
<polygon fill="black" stroke="black" points="222.59,-285.52 230.8,-278.82 220.21,-278.94 222.59,-285.52"/>
</g>
<!-- Error -->
<g id="node4" class="node">
<title>Error</title>
<ellipse fill="none" stroke="black" cx="435.6" cy="-192" rx="36.29" ry="18"/>
<text text-anchor="middle" x="435.6" y="-188.3" font-family="Times,serif" font-size="14.00">Error</text>
<ellipse fill="none" stroke="black" cx="52.19" cy="-105" rx="36.29" ry="18"/>
<text text-anchor="middle" x="52.19" y="-101.3" font-family="Times,serif" font-size="14.00">Error</text>
</g>
<!-- Initialized&#45;&gt;Error -->
<g id="edge3" class="edge">
<title>Initialized&#45;&gt;Error</title>
<path fill="none" stroke="black" d="M351.29,-407.01C367,-367.13 406.34,-267.27 425.2,-219.4"/>
<polygon fill="black" stroke="black" points="428.49,-220.6 428.9,-210.01 421.97,-218.03 428.49,-220.6"/>
<path fill="none" stroke="black" d="M68.84,-319.64C65.73,-279.74 58.06,-181.27 54.32,-133.24"/>
<polygon fill="black" stroke="black" points="57.8,-132.95 53.54,-123.25 50.83,-133.49 57.8,-132.95"/>
</g>
<!-- Running_Sys -->
<g id="node5" class="node">
<title>Running_Sys</title>
<ellipse fill="none" stroke="black" cx="232.6" cy="-279" rx="70.69" ry="18"/>
<text text-anchor="middle" x="232.6" y="-275.3" font-family="Times,serif" font-size="14.00">Running_Sys</text>
<ellipse fill="none" stroke="black" cx="266.19" cy="-192" rx="70.69" ry="18"/>
<text text-anchor="middle" x="266.19" y="-188.3" font-family="Times,serif" font-size="14.00">Running_Sys</text>
</g>
<!-- Runnable&#45;&gt;Running_Sys -->
<g id="edge4" class="edge">
<title>Runnable&#45;&gt;Running_Sys</title>
<path fill="none" stroke="black" d="M232.6,-333.81C232.6,-325.79 232.6,-316.05 232.6,-307.07"/>
<polygon fill="black" stroke="black" points="236.1,-307.03 232.6,-297.03 229.1,-307.03 236.1,-307.03"/>
<path fill="none" stroke="black" d="M266.19,-246.81C266.19,-238.79 266.19,-229.05 266.19,-220.07"/>
<polygon fill="black" stroke="black" points="269.69,-220.03 266.19,-210.03 262.69,-220.03 269.69,-220.03"/>
</g>
<!-- Running_Sys&#45;&gt;Error -->
<g id="edge10" class="edge">
<g id="edge7" class="edge">
<title>Running_Sys&#45;&gt;Error</title>
<path fill="none" stroke="black" d="M278.15,-265.13C297.66,-259.14 320.53,-251.46 340.6,-243 362.39,-233.81 385.92,-221.45 404.1,-211.32"/>
<polygon fill="black" stroke="black" points="406.1,-214.21 413.09,-206.25 402.66,-208.11 406.1,-214.21"/>
<path fill="none" stroke="black" d="M202.68,-183.96C173.38,-178.94 138.83,-170.41 110.19,-156 96.75,-149.24 83.86,-138.69 73.66,-129.01"/>
<polygon fill="black" stroke="black" points="76,-126.4 66.42,-121.87 71.08,-131.38 76,-126.4"/>
</g>
<!-- Running_User -->
<g id="node6" class="node">
<title>Running_User</title>
<ellipse fill="none" stroke="black" cx="304.6" cy="-192" rx="76.89" ry="18"/>
<text text-anchor="middle" x="304.6" y="-188.3" font-family="Times,serif" font-size="14.00">Running_User</text>
<ellipse fill="none" stroke="black" cx="226.19" cy="-18" rx="76.89" ry="18"/>
<text text-anchor="middle" x="226.19" y="-14.3" font-family="Times,serif" font-size="14.00">Running_User</text>
</g>
<!-- Running_Sys&#45;&gt;Running_User -->
<g id="edge12" class="edge">
<g id="edge9" class="edge">
<title>Running_Sys&#45;&gt;Running_User</title>
<path fill="none" stroke="black" d="M260.51,-262.41C268.39,-257.03 276.48,-250.45 282.6,-243 288.24,-236.12 292.71,-227.57 296.09,-219.49"/>
<polygon fill="black" stroke="black" points="299.41,-220.61 299.7,-210.02 292.87,-218.12 299.41,-220.61"/>
<text text-anchor="middle" x="313.6" y="-231.8" font-family="Times,serif" font-size="14.00">return</text>
<path fill="none" stroke="black" d="M256.46,-174C249.29,-160.59 239.98,-141.19 235.19,-123 228.52,-97.63 226.52,-67.69 226.04,-46.47"/>
<polygon fill="black" stroke="black" points="229.53,-46.19 225.91,-36.24 222.53,-46.28 229.53,-46.19"/>
<text text-anchor="middle" x="258.19" y="-101.3" font-family="Times,serif" font-size="14.00">return</text>
</g>
<!-- Asleep -->
<g id="node9" class="node">
<g id="node7" class="node">
<title>Asleep</title>
<ellipse fill="none" stroke="black" cx="41.6" cy="-192" rx="41.69" ry="18"/>
<text text-anchor="middle" x="41.6" y="-188.3" font-family="Times,serif" font-size="14.00">Asleep</text>
<ellipse fill="none" stroke="black" cx="600.19" cy="-105" rx="41.69" ry="18"/>
<text text-anchor="middle" x="600.19" y="-101.3" font-family="Times,serif" font-size="14.00">Asleep</text>
</g>
<!-- Running_Sys&#45;&gt;Asleep -->
<g id="edge9" class="edge">
<g id="edge6" class="edge">
<title>Running_Sys&#45;&gt;Asleep</title>
<path fill="none" stroke="black" d="M195.57,-263.48C180.32,-257.35 162.52,-250.03 146.6,-243 123.31,-232.73 97.5,-220.45 77.3,-210.63"/>
<polygon fill="black" stroke="black" points="78.68,-207.41 68.16,-206.17 75.61,-213.7 78.68,-207.41"/>
<text text-anchor="middle" x="165.6" y="-231.8" font-family="Times,serif" font-size="14.00">sleep</text>
<path fill="none" stroke="black" d="M318.7,-179.8C375.79,-167.3 469.52,-145.8 549.19,-123 552.38,-122.09 555.66,-121.1 558.95,-120.08"/>
<polygon fill="black" stroke="black" points="560.31,-123.32 568.77,-116.95 558.18,-116.65 560.31,-123.32"/>
<text text-anchor="middle" x="499.19" y="-144.8" font-family="Times,serif" font-size="14.00">sleep</text>
</g>
<!-- Returned -->
<g id="node10" class="node">
<g id="node8" class="node">
<title>Returned</title>
<ellipse fill="none" stroke="black" cx="155.6" cy="-192" rx="53.89" ry="18"/>
<text text-anchor="middle" x="155.6" y="-188.3" font-family="Times,serif" font-size="14.00">Returned</text>
<ellipse fill="none" stroke="black" cx="486.19" cy="-105" rx="53.89" ry="18"/>
<text text-anchor="middle" x="486.19" y="-101.3" font-family="Times,serif" font-size="14.00">Returned</text>
</g>
<!-- Running_Sys&#45;&gt;Returned -->
<g id="edge11" class="edge">
<title>Running_Sys&#45;&gt;Returned</title>
<path fill="none" stroke="black" d="M217.38,-261.21C205.92,-248.55 190.04,-231.03 177.25,-216.91"/>
<polygon fill="black" stroke="black" points="179.82,-214.53 170.52,-209.47 174.64,-219.23 179.82,-214.53"/>
</g>
<!-- Running_User&#45;&gt;Running_Sys -->
<g id="edge6" class="edge">
<title>Running_User&#45;&gt;Running_Sys</title>
<path fill="none" stroke="black" d="M258.8,-206.54C248.87,-211.65 239.57,-218.61 233.6,-228 229.32,-234.72 227.98,-243.05 228.02,-250.97"/>
<polygon fill="black" stroke="black" points="224.54,-251.26 228.74,-260.98 231.52,-250.75 224.54,-251.26"/>
<text text-anchor="middle" x="258.1" y="-231.8" font-family="Times,serif" font-size="14.00">syscall</text>
</g>
<!-- Interrupted -->
<g id="node7" class="node">
<title>Interrupted</title>
<ellipse fill="none" stroke="black" cx="348.6" cy="-105" rx="64.99" ry="18"/>
<text text-anchor="middle" x="348.6" y="-101.3" font-family="Times,serif" font-size="14.00">Interrupted</text>
</g>
<!-- Running_User&#45;&gt;Interrupted -->
<g id="edge5" class="edge">
<title>Running_User&#45;&gt;Interrupted</title>
<path fill="none" stroke="black" d="M313.5,-173.8C319.74,-161.74 328.2,-145.4 335.25,-131.79"/>
<polygon fill="black" stroke="black" points="338.37,-133.38 339.86,-122.89 332.15,-130.16 338.37,-133.38"/>
<text text-anchor="middle" x="361.6" y="-144.8" font-family="Times,serif" font-size="14.00">interrupt</text>
</g>
<!-- Interrupted&#45;&gt;Running_User -->
<g id="edge8" class="edge">
<title>Interrupted&#45;&gt;Running_User</title>
<path fill="none" stroke="black" d="M333.3,-122.56C328.75,-128.12 324.05,-134.55 320.6,-141 316.76,-148.15 313.66,-156.37 311.25,-164.05"/>
<polygon fill="black" stroke="black" points="307.87,-163.13 308.46,-173.71 314.59,-165.07 307.87,-163.13"/>
<title>Running_Sys&#45;&gt;Returned</title>
<path fill="none" stroke="black" d="M312.74,-178.34C333.61,-172.25 358.38,-164.45 380.19,-156 403.62,-146.93 429.1,-134.98 449.21,-125.04"/>
<polygon fill="black" stroke="black" points="450.95,-128.09 458.33,-120.49 447.82,-121.82 450.95,-128.09"/>
</g>
<!-- Preempted -->
<g id="node8" class="node">
<g id="node9" class="node">
<title>Preempted</title>
<ellipse fill="none" stroke="black" cx="271.6" cy="-18" rx="61.99" ry="18"/>
<text text-anchor="middle" x="271.6" y="-14.3" font-family="Times,serif" font-size="14.00">Preempted</text>
<ellipse fill="none" stroke="black" cx="352.19" cy="-105" rx="61.99" ry="18"/>
<text text-anchor="middle" x="352.19" y="-101.3" font-family="Times,serif" font-size="14.00">Preempted</text>
</g>
<!-- Interrupted&#45;&gt;Preempted -->
<g id="edge7" class="edge">
<title>Interrupted&#45;&gt;Preempted</title>
<path fill="none" stroke="black" d="M333.38,-87.21C321.92,-74.55 306.04,-57.03 293.25,-42.91"/>
<polygon fill="black" stroke="black" points="295.82,-40.53 286.52,-35.47 290.64,-45.23 295.82,-40.53"/>
<text text-anchor="middle" x="345.1" y="-57.8" font-family="Times,serif" font-size="14.00">preempt</text>
<!-- Running_Sys&#45;&gt;Preempted -->
<g id="edge10" class="edge">
<title>Running_Sys&#45;&gt;Preempted</title>
<path fill="none" stroke="black" d="M283.18,-174.21C296.11,-161.43 314.05,-143.7 328.4,-129.52"/>
<polygon fill="black" stroke="black" points="330.88,-131.99 335.53,-122.47 325.96,-127.01 330.88,-131.99"/>
<text text-anchor="middle" x="345.69" y="-144.8" font-family="Times,serif" font-size="14.00">preempt</text>
</g>
<!-- Preempted&#45;&gt;Running_User -->
<g id="edge13" class="edge">
<title>Preempted&#45;&gt;Running_User</title>
<path fill="none" stroke="black" d="M270.09,-36.18C268.73,-57.01 267.83,-93.05 274.6,-123 277.85,-137.4 284.19,-152.51 290.2,-164.82"/>
<polygon fill="black" stroke="black" points="287.23,-166.71 294.89,-174.03 293.47,-163.53 287.23,-166.71"/>
<!-- Running_User&#45;&gt;Running_Sys -->
<g id="edge5" class="edge">
<title>Running_User&#45;&gt;Running_Sys</title>
<path fill="none" stroke="black" d="M196.06,-34.66C163.08,-53.98 117.48,-88.54 138.19,-123 153.49,-148.45 181.89,-164.89 208.05,-175.21"/>
<polygon fill="black" stroke="black" points="206.97,-178.54 217.56,-178.74 209.4,-171.98 206.97,-178.54"/>
<text text-anchor="middle" x="171.19" y="-101.3" font-family="Times,serif" font-size="14.00">interrupt</text>
</g>
<!-- Asleep&#45;&gt;Runnable -->
<g id="edge15" class="edge">
<g id="edge13" class="edge">
<title>Asleep&#45;&gt;Runnable</title>
<path fill="none" stroke="black" d="M46.7,-210.08C54.3,-232.82 70.67,-272.97 97.6,-297 120.32,-317.28 151.62,-330.45 178.36,-338.69"/>
<polygon fill="black" stroke="black" points="177.4,-342.06 187.98,-341.51 179.37,-335.34 177.4,-342.06"/>
<text text-anchor="middle" x="125.1" y="-275.3" font-family="Times,serif" font-size="14.00">wakeup</text>
<path fill="none" stroke="black" d="M579.26,-120.81C563.89,-131.34 542.26,-145.43 522.19,-156 450.82,-193.58 363.46,-228.15 311.45,-247.6"/>
<polygon fill="black" stroke="black" points="310,-244.41 301.85,-251.17 312.44,-250.97 310,-244.41"/>
<text text-anchor="middle" x="512.69" y="-188.3" font-family="Times,serif" font-size="14.00">wakeup</text>
</g>
<!-- Complete -->
<g id="node11" class="node">
<g id="node10" class="node">
<title>Complete</title>
<ellipse fill="none" stroke="black" cx="151.6" cy="-105" rx="55.49" ry="18"/>
<text text-anchor="middle" x="151.6" y="-101.3" font-family="Times,serif" font-size="14.00">Complete</text>
<ellipse fill="none" stroke="black" cx="486.19" cy="-18" rx="55.49" ry="18"/>
<text text-anchor="middle" x="486.19" y="-14.3" font-family="Times,serif" font-size="14.00">Complete</text>
</g>
<!-- Returned&#45;&gt;Complete -->
<g id="edge14" class="edge">
<g id="edge12" class="edge">
<title>Returned&#45;&gt;Complete</title>
<path fill="none" stroke="black" d="M153.91,-173.93C153.4,-168.23 152.91,-161.85 152.6,-156 152.21,-148.66 151.97,-140.71 151.82,-133.35"/>
<polygon fill="black" stroke="black" points="155.32,-133.08 151.66,-123.13 148.32,-133.19 155.32,-133.08"/>
<text text-anchor="middle" x="197.1" y="-144.8" font-family="Times,serif" font-size="14.00">exit_success</text>
<path fill="none" stroke="black" d="M486.19,-86.8C486.19,-75.16 486.19,-59.55 486.19,-46.24"/>
<polygon fill="black" stroke="black" points="489.69,-46.18 486.19,-36.18 482.69,-46.18 489.69,-46.18"/>
<text text-anchor="middle" x="530.69" y="-57.8" font-family="Times,serif" font-size="14.00">exit_success</text>
</g>
<!-- Preempted&#45;&gt;Running_User -->
<g id="edge11" class="edge">
<title>Preempted&#45;&gt;Running_User</title>
<path fill="none" stroke="black" d="M328.79,-88.21C309.06,-74.9 280.62,-55.72 258.69,-40.92"/>
<polygon fill="black" stroke="black" points="260.58,-37.97 250.33,-35.28 256.66,-43.78 260.58,-37.97"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

@ -1,7 +1,5 @@
#!/bin/bash
LLVM_VERSION=13
validate() {
utility="clang-format"
utility_version="$("$utility" --version 2> /dev/null)" || {
@ -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=9
declare -i required_minor=0
declare -i required_patch=0
@ -45,16 +43,16 @@ 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 "runtime/tests/gocr" -o -path "runtime/tests/TinyEKF" -o -path "runtime/tests/CMSIS_5_NN" -o -path "runtime/tests/sod" -o -path "runtime/tests/**/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 \
-type f \( -iname \*.h -o -iname \*.c -o -iname \*.s \) -print0 \
| xargs --null clang-format -i
\( -path "runtime/thirdparty" -o -path "runtime/tests/gocr" -o -path "runtime/tests/TinyEKF" -o -path "runtime/tests/CMSIS_5_NN" -o -path "runtime/tests/sod" -o -path "runtime/tests/**/thirdparty" \) -prune -false -o \
-type f \( -iname \*.h -o -iname \*.c -o -iname \*.s \) -print \
| xargs clang-format -i
}
case $1 in

@ -0,0 +1,147 @@
#!/bin/bash
# This script is responsible for copying, linking, and aliasing all of our build tools such that they are
# in known paths that we can add to PATH and LD_LIBRARY_PATH. The binaries go into "${SYS_PREFIX}/bin" and
# the libraries go into "${SYS_PREFIX}/lib". By default, SYS_PREFIX is `/opt/sledge/`, which means that this
# script is assumed to be executed as root, as in our Docker build container. However, by by setting
# SYS_PREFIX to a directory that the user has access to, this can be avoided.
#
# For example, in the GitHub Actions workflow, SYS_PREFIX is set to the topmost project directory and the
# environment is updated as follows.
#
# SYS_PREFIX="$(pwd)" ./install.sh
# PATH="$(pwd)/bin:$PATH"
# LD_LIBRARY_PATH="$(pwd)/lib:$LD_LIBRARY_PATH"
#
# This is currently executed
# - Indirectly via `make install` in the root Makefile, typically when the sledge-dev build container is built
# - Directly by the GitHub workflow
#
# The script takes either wasmception or wasi as the first argument to install either wasmception or WASI-SDK
# If no argument is provided, wasmception is assumed
# If either wasmception or wasi is provided, an additional `-d` or `--dry-run` flag can be provided to view the commands
# and paths that would be generated. This is helpful for sanity checking when setting SYS_PREFIX and using in a new context
echo "Setting up toolchain environment"
for last_arg in "$@"; do :; done
if [[ $last_arg == "-d" ]] || [[ $last_arg == "--dry-run" ]]; then
DRY_RUN=true
else
DRY_RUN=false
fi
if $DRY_RUN; then
DRY_RUN_PREFIX=echo
else
DRY_RUN_PREFIX=
fi
# Get the absolute path of the topmost project directly
# The use of dirname is particular. It seems unneccesary how this script is run
SYS_SRC_PREFIX=${SYS_SRC_PREFIX:-"$(
cd "$(dirname "$(dirname "${0}")")" || exit 1
pwd -P
)"}
$DRY_RUN && echo SYS_SRC_PREFIX: "$SYS_SRC_PREFIX"
# And check for the presence of this script to make sure we got it right
if [ ! -x "${SYS_SRC_PREFIX}/install.sh" ]; then
echo "Unable to find the install script" >&2
exit 1
fi
SYS_NAME='sledge'
COMPILER='awsm'
COMPILER_EXECUTABLE=$COMPILER
# /opt/sledge
SYS_PREFIX=${SYS_PREFIX:-"/opt/${SYS_NAME}"}
$DRY_RUN && echo SYS_PREFIX: "$SYS_PREFIX"
# /sledge, where the sledge repo is mounted from the host
SYS_SRC_PREFIX=${SYS_SRC_PREFIX:-"/${SYS_NAME}"}
$DRY_RUN && echo SYS_SRC_PREFIX: "$SYS_SRC_PREFIX"
# The release directory containing the binary of the aWsm compiler
SYS_COMPILER_REL_DIR=${SYS_COMPILER_REL_DIR:-"${SYS_SRC_PREFIX}/${COMPILER}/target/release"}
$DRY_RUN && echo SYS_COMPILER_REL_DIR: "$SYS_COMPILER_REL_DIR"
# /opt/sledge/bin
SYS_BIN_DIR=${SYS_BIN_DIR:-"${SYS_PREFIX}/bin"}
$DRY_RUN && echo SYS_BIN_DIR: "$SYS_BIN_DIR"
# /opt/sledge/lib
SYS_LIB_DIR=${SYS_LIB_DIR:-"${SYS_PREFIX}/lib"}
$DRY_RUN && echo SYS_LIB_DIR: "$SYS_LIB_DIR"
# The first argument can be either wasi or wasmception. This determines the system interface used
# The default is wasmception
# Currently, WASI is not actually supported by the runtime.
if [ $# -eq 0 ] || [ "$1" = "wasmception" ]; then
echo "Setting up for wasmception"
WASM_PREFIX=${WASM_PREFIX:-"${SYS_SRC_PREFIX}/${COMPILER}/wasmception"}
WASM_BIN=${WASM_BIN:-"${WASM_PREFIX}/dist/bin"}
WASM_SYSROOT=${WASM_SYSROOT:-"${WASM_PREFIX}/sysroot"}
WASM_TARGET=${WASM_TARGET:-"wasm32-unknown-unknown-wasm"}
WASM_BIN_PREFIX=${WASM_BIN_PREFIX:-"$WASM_TARGET"}
WASM_TOOLS=(ar)
elif [ "$1" = "wasi" ]; then
echo "Setting up for wasi-sdk"
WASM_PREFIX=${WASM_PREFIX:-${WASM_SDK:-"/opt/wasi-sdk"}}
WASM_BIN=${WASM_BIN:-"${WASM_PREFIX}/bin"}
WASM_SYSROOT=${WASM_SYSROOT:-"${WASM_PREFIX}/share/sysroot"}
WASM_TARGET=${WASM_TARGET:-"wasm32-wasi"}
WASM_BIN_PREFIX=${WASM_BIN_PREFIX:-"$WASM_TARGET"}
WASM_TOOLS=(ar dwarfdump nm ranlib size)
fi
$DRY_RUN && echo WASM_PREFIX: "$WASM_PREFIX"
$DRY_RUN && echo WASM_BIN: "$WASM_BIN"
$DRY_RUN && echo WASM_SYSROOT: "$WASM_SYSROOT"
$DRY_RUN && echo WASM_TARGET: "$WASM_TARGET"
$DRY_RUN && echo WASM_BIN_PREFIX: "$WASM_BIN_PREFIX"
$DRY_RUN && echo WASM_TOOLS: "${WASM_TOOLS[@]}"
# Delete all existing installations of the binaries
$DRY_RUN_PREFIX rm -f "${SYS_BIN_DIR}"/*
# And reinstall
$DRY_RUN_PREFIX install -d -v "$SYS_BIN_DIR" || exit 1
# Symbolically link the Awsm compiler
# /sledge/awsm/target/release/silverfish /opt/sledge/bin/awsm
$DRY_RUN_PREFIX ln -sfv "${SYS_COMPILER_REL_DIR}/${COMPILER_EXECUTABLE}" "${SYS_BIN_DIR}/${COMPILER_EXECUTABLE}"
# Generate shell script stubs that act as aliases that automatically set the approproiate target and sysroot
# for either Wasmception or WASI-SDK
# For example, when wasmception is set, calling `wasm32-unknown-unknown-wasm-clang` results in
# `exec "/sledge/awsm/wasmception/dist/bin/clang" --target="wasm32-unknown-unknown-wasm" --sysroot="/sledge/awsm/wasmception/sysroot" "$@"`
for file in clang clang++; do
wrapper_file="$(mktemp)"
cat > "$wrapper_file" << EOT
#! /bin/sh
exec "${WASM_BIN}/${file}" --target="$WASM_TARGET" --sysroot="$WASM_SYSROOT" "\$@"
EOT
cat "$wrapper_file"
$DRY_RUN_PREFIX install -p -v "$wrapper_file" "${SYS_BIN_DIR}/${WASM_BIN_PREFIX}-${file}"
$DRY_RUN && echo rm -f "$wrapper_file"
rm -f "$wrapper_file"
done
# Link the LLVM Tools with the proper prefix
for file in "${WASM_TOOLS[@]}"; do
$DRY_RUN_PREFIX ln -sfv "${WASM_BIN}/llvm-${file}" "${SYS_BIN_DIR}/${WASM_BIN_PREFIX}-${file}"
done
# Link any other tools with the proper prefix
OTHER_TOOLS=(ld)
for file in "${OTHER_TOOLS[@]}"; do
$DRY_RUN_PREFIX ln -sfv "${WASM_BIN}/wasm-${file}" "${SYS_BIN_DIR}/${WASM_BIN_PREFIX}-${file}"
done
# Link clang as gcc if needed
$DRY_RUN_PREFIX ln -svf "${SYS_BIN_DIR}/${WASM_BIN_PREFIX}-clang" "${SYS_BIN_DIR}/${WASM_BIN_PREFIX}-gcc"
$DRY_RUN_PREFIX ln -svf "${SYS_BIN_DIR}/${WASM_BIN_PREFIX}-clang++" "${SYS_BIN_DIR}/${WASM_BIN_PREFIX}-g++"
echo "Done!"

@ -1,78 +0,0 @@
#!/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
ARCH=$(uname -m)
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
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
fi
sudo apt-get update && sudo apt-get install -y --no-install-recommends \
apt-utils \
man-db \
&& yes | unminimize
sudo apt-get update && sudo apt-get install -y --no-install-recommends \
automake \
bc \
bsdmainutils \
build-essential \
binutils-dev \
ca-certificates \
cmake \
curl \
fonts-dejavu \
fonts-cascadia-code \
fonts-roboto \
gdb \
git \
gpg-agent \
gnuplot \
hey \
httpie \
imagemagick \
jq \
less \
libssl-dev \
libtinfo5 \
libtool \
libz3-4 \
lsb-release \
make \
netpbm \
openssh-client \
pango1.0-tools \
pkg-config \
shellcheck \
software-properties-common \
strace \
valgrind \
wabt \
wamerican \
wget
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
fi
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --default-toolchain stable --component rustfmt --target wasm32-wasi -y
echo "Run 'source ~/.bashrc'"

@ -1,35 +1,39 @@
#!/bin/bash
# Installs LLVM tooling, delegating the to the LLVM script as much as possible
# We need to shim support for LLVM 8 because the LLVM script only supports 9-12
LLVM_VERSION=$1
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"
if [[ "$LLVM_VERSION" -gt 8 ]]; then
curl --proto '=https' --tlsv1.2 -sSf https://apt.llvm.org/llvm.sh | bash -s -- "$LLVM_VERSION"
else
apt-get install -y --no-install-recommends \
"clang-$LLVM_VERSION" \
"lldb-$LLVM_VERSION" \
"lld-$LLVM_VERSION" \
"clangd-$LLVM_VERSION"
fi
# 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" \
"clang-tools-$LLVM_VERSION" \
"clang-tidy-$LLVM_VERSION" \
"clang-format-$LLVM_VERSION"
"libc++1-$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
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/clang-tidy clang-tidy "/usr/bin/clang-tidy-$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
# Explicitly use at least clang-format-11 to format source because of changes between 10 and 11
if [[ "$LLVM_VERSION" -ge 11 ]]; then
apt-get install -y --no-install-recommends \
"clang-format-$LLVM_VERSION"
update-alternatives --install /usr/bin/clang-format clang-format "/usr/bin/clang-format-$LLVM_VERSION" 100
else
apt-get install -y --no-install-recommends \
"clang-format-11"
update-alternatives --install /usr/bin/clang-format clang-format "/usr/bin/clang-format-11" 100
fi

@ -1,37 +0,0 @@
CFILES := src/*.c
INCLUDES := -Iinclude/
# fPIC = Position Independent Code, necessary for linking to relative addresses.
CFLAGS := -fPIC -O3 -flto -ftls-model=initial-exec
# Strips out calls to assert() and disables debuglog
CFLAGS+=-DNDEBUG
# CFI Sanitizer
# CFLAGS+=-fvisibility=default -fsanitize=cfi
# Undefined Sanitizer - https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
# CFLAGS+=-fsanitize=undefined,float-divide-by-zero,unsigned-integer-overflow,implicit-conversion,local-bounds,nullability
# Address Sanitizer - "Fast Memory Error Detector" - https://clang.llvm.org/docs/AddressSanitizer.html
# CFLAGS+=-fsanitize=address -fno-omit-frame-pointer
# Clang SafeStack - https://clang.llvm.org/docs/SafeStack.html
# CFLAGS+=-fsanitize=safe-stack
# Memory Sanitizer - https://clang.llvm.org/docs/MemorySanitizer.html
# CFLAGS+=-fsanitize=memory -fno-omit-frame-pointer
all: dist/libsledge.a
dist:
mkdir -p dist
dist/%.o: src/%.c dist
clang ${CFLAGS} -c ${INCLUDES} -o $@ $<
dist/libsledge.a: dist/control_instructions.o dist/memory_instructions.o dist/numeric_instructions.o dist/table_instructions.o dist/variable_instructions.o dist/instantiation.o dist/wasi_snapshot_preview1.o dist/sledge_extensions.o
ar rcs dist/libsledge.a $^
clean:
rm -rf dist

@ -1,156 +0,0 @@
---
geometry: margin=2cm
---
# libsledge Binary Interfaces
libsledge is a \*.a static library (archive) that is statically linked with a \*.bc file generated by the aWsm compiler when compiling to a \*.so Linux shared library that can be loaded and executed by the sledgert runtime.
The static library internally implements the aWsm ABI in order to link to the \*.bc file generated by the aWsm compiler. [See the relevant documentation for this ABI here](../awsm/doc/abi.md).
libsledge defines a ABI between the sledgert runtime and a \*.so shared library containing an executable serverless function. This is distinct from the aWsm ABI.
# SLEdge \*.so serverless module
A SLEdge \*.so serverless module is generated by the latter portion of the aWsm/SLEdge toolchain.
The first portion of the toolchain is responsible for compiling a source program into a WebAssembly module. This is handled by standard compilers capable of emitting WebAssembly.
The second portion of the toolchain is the aWsm compiler, which generates a \*.bc file with a well defined ABI.
The third portion of the toolchain is the LLVM compiler, which ingests a \*.bc file emitted by aWsm and the libsledge static library, and emits a SLEdge \*.so serverless module.
## Architecture
In order to reduce the overhead of calling sledgert functions, libsledge operates on global state of type `sledge_abi__wasm_module_instance` at `sledge_abi__current_wasm_module_instance`. This represents the global state of the wasm32 context executing on a sledgert worker core. The scheduler is responsible for populating these symbols before yielding execution to a serverless function.
The `sledge_abi__wasm_module_instance` structure includes the WebAssembly function table and the WebAssembly linear memory. This subset was selected because the author believes that use of function pointers and linear memory is frequent enough that LTO when compiling the \*.so file is beneficial.
## WebAssembly Instruction Implementation
Here is a list of WebAssembly instructions that depend on symbols from libsledge, libc, or sledgert (via the SLEdge ABI).
### [Control Instructions](https://webassembly.github.io/spec/core/syntax/instructions.html#control-instructions)
| Instruction | aWsm ABI | libc Dependencies | SLEdge ABI |
| ------------- | ------------------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| call_indirect | `get_function_from_table` | `stderr`, `fprintf` | `sledge_abi__current_wasm_module_instance.table`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_INVALID_INDEX`, `WASM_TRAP_MISMATCHED_TYPE` |
### [Variable Instructions](https://webassembly.github.io/spec/core/syntax/instructions.html#variable-instructions)
| Instruction | aWsm ABI | libc Dependencies | SLEdge ABI |
| ----------- | ---------------------------------- | ----------------- | ---------------------------------------------------------------------- |
| global.get | `get_global_i32`, `get_global_i64` | None | `sledge_abi__wasm_globals_get_i32`, `sledge_abi__wasm_globals_get_i64` |
| global.set | `set_global_i32`, `set_global_i64` | None | `sledge_abi__wasm_globals_set_i32`, `sledge_abi__wasm_globals_set_i64` |
### [Numeric Instructions](https://webassembly.github.io/spec/core/syntax/instructions.html#numeric-instructions)
| Instruction | aWsm ABI | libc Dependencies | SLEdge ABI |
| --------------- | ---------------------------------------- | --------------------------------------------- | ----------------------------------------------------------------------- |
| i32.div_s | `i32_div` ("fast unsafe" disabled) | `stderr`, `fprintf` | `sledge_abi__wasm_trap_raise`, `WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION` |
| i32.div_u | `u32_div` ("fast unsafe" disabled) | `stderr`, `fprintf` | `sledge_abi__wasm_trap_raise`, `WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION` |
| i32.rem_s | `i32_rem` ("fast unsafe" disabled) | `stderr`, `fprintf` | `sledge_abi__wasm_trap_raise`, `WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION` |
| i32.rem_u | `u32_rem` ("fast unsafe" disabled) | `stderr`, `fprintf` | `sledge_abi__wasm_trap_raise`, `WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION` |
| i32.rotl | `rotl_u32` | None | None |
| i32.rotr | `rotr_u32` | None | None |
| i32.trunc_f32_s | `i32_trunc_f32` ("fast unsafe" disabled) | `stderr`, `fprintf` | `sledge_abi__wasm_trap_raise`, `WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION` |
| i32.trunc_f32_u | `u32_trunc_f32` ("fast unsafe" disabled) | `stderr`, `fprintf` | `sledge_abi__wasm_trap_raise`, `WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION` |
| i32.trunc_f64_s | `i32_trunc_f64` ("fast unsafe" disabled) | `INT32_MIN`, `INT32_MAX`, `stderr`, `fprintf` | `sledge_abi__wasm_trap_raise`, `WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION` |
| i32.trunc_f64_u | `u32_trunc_f64` ("fast unsafe" disabled) | `UINT32_MAX`, `stderr`, `fprintf` | `sledge_abi__wasm_trap_raise`, `WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION` |
| i64.div_s | `i64_div` ("fast unsafe" disabled) | `stderr`, `fprintf` | `sledge_abi__wasm_trap_raise`, `WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION` |
| i64.div_u | `u64_div` ("fast unsafe" disabled) | `stderr`, `fprintf` | `sledge_abi__wasm_trap_raise`, `WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION` |
| i64.rem_s | `i64_rem` ("fast unsafe" disabled) | `INT32_MIN`, `stderr`, `fprintf` | `sledge_abi__wasm_trap_raise`, `WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION` |
| i64.rem_u | `u64_rem` ("fast unsafe" disabled) | `stderr`, `fprintf` | `sledge_abi__wasm_trap_raise`, `WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION` |
| i64.rotl | `rotl_u64` | **NOT SUPPORTED** | **NOT SUPPORTED** |
| i64.rotr | `rotr_u64` | **NOT SUPPORTED** | **NOT SUPPORTED** |
| i64.trunc_f32_s | `i64_trunc_f32` | `INT64_MIN`, `INT64_MAX`, `stderr`, `fprintf` | `sledge_abi__wasm_trap_raise`, `WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION` |
| i64.trunc_f32_u | `u64_trunc_f32` | `UINT64_MAX`, `stderr`, `fprintf` | `sledge_abi__wasm_trap_raise`, `WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION` |
| i64.trunc_f64_s | `i64_trunc_f64` | `INT64_MIN`, `INT64_MAX`, `stderr`, `fprintf` | `sledge_abi__wasm_trap_raise`, `WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION` |
| i64.trunc_f64_u | `u64_trunc_f64` | `UINT64_MAX`, `stderr`, `fprintf` | `sledge_abi__wasm_trap_raise`, `WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION` |
| f32.ceil | `f32_ceil` | `ceilf` | `ceilf` |
| f32.copysign | `f32_copysign` | `copysignf` | `copysignf` |
| f32.floor | `f32_floor` | `floorf` | `floorf` |
| f32.max | `f32_max` | None | None |
| f32.min | `f32_min` | None | None |
| f32.nearest | `f32_nearest` | `nearbyintf` | `nearbyintf` |
| f32.trunc | `f32_trunc_f32` | `truncf` | `truncf` |
| f64.ceil | `f64_ceil` | `ceil` | `ceil` |
| f64.copysign | `f64_copysign` | `copysign` | `copysign` |
| f64.floor | `f64_floor` | `floor` | `floor` |
| f64.max | `f64_max` | None | None |
| f64.min | `f64_min` | None | None |
| f64.nearest | `f64_nearest` | `nearbyint` | `nearbyint` |
| f64.trunc | `f64_trunc_f64` | `trunc` | `trunc` |
### [Memory Instructions](https://webassembly.github.io/spec/core/syntax/instructions.html#memory-instructions)
| instruction | aWsm ABI | libc Dependencies | SLEdge ABI |
| ------------ | ------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| i32.load | `get_i32` | `fprintf`, `stderr` | `sledge_abi__current_wasm_module_instance.memory`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY` |
| i32.load8_s | `get_i8` | `fprintf`, `stderr` | `sledge_abi__current_wasm_module_instance.memory`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY` |
| i32.load8_u | `get_i8` | `fprintf`, `stderr` | `sledge_abi__current_wasm_module_instance.memory`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY` |
| i32.load16_s | `get_i16` | `fprintf`, `stderr` | `sledge_abi__current_wasm_module_instance.memory`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY` |
| i32.load16_u | `get_i16` | `fprintf`, `stderr` | `sledge_abi__current_wasm_module_instance.memory`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY` |
| i32.store | `set_i32` | `fprintf`, `stderr` | `sledge_abi__current_wasm_module_instance.memory`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY` |
| i32.store8 | `set_i8` | `fprintf`, `stderr` | `sledge_abi__current_wasm_module_instance.memory`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY` |
| i32.store16 | `set_i16` | `fprintf`, `stderr` | `sledge_abi__current_wasm_module_instance.memory`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY` |
| i64.load | `get_i64` | `fprintf`, `stderr` | `sledge_abi__current_wasm_module_instance.memory`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY` |
| i64.load8_s | `get_i8` | `fprintf`, `stderr` | `sledge_abi__current_wasm_module_instance.memory`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY` |
| i64.load8_u | `get_i8` | `fprintf`, `stderr` | `sledge_abi__current_wasm_module_instance.memory`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY` |
| i64.load16_s | `get_i16` | `fprintf`, `stderr` | `sledge_abi__current_wasm_module_instance.memory`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY` |
| i64.load16_u | `get_i16` | `fprintf`, `stderr` | `sledge_abi__current_wasm_module_instance.memory`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY` |
| i64.load32_s | `get_i32` | `fprintf`, `stderr` | `sledge_abi__current_wasm_module_instance.memory`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY` |
| i64.load32_u | `get_i32` | `fprintf`, `stderr` | `sledge_abi__current_wasm_module_instance.memory`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY` |
| i64.store | `set_i64` | `fprintf`, `stderr` | `sledge_abi__current_wasm_module_instance.memory`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY` |
| i64.store8 | `set_i8` | `fprintf`, `stderr` | `sledge_abi__current_wasm_module_instance.memory`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY` |
| i64.store16 | `set_i16` | `fprintf`, `stderr` | `sledge_abi__current_wasm_module_instance.memory`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY` |
| i64.store32 | `set_i32` | `fprintf`, `stderr` | `sledge_abi__current_wasm_module_instance.memory`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY` |
| f32.load | `get_f32` | `fprintf`, `stderr` | `sledge_abi__current_wasm_module_instance.memory`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY` |
| f32.store | `set_f32` | `fprintf`, `stderr` | `sledge_abi__current_wasm_module_instance.memory`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY` |
| f64.load | `get_f64` | `fprintf`, `stderr` | `sledge_abi__current_wasm_module_instance.memory`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY` |
| f64.store | `set_f64` | `fprintf`, `stderr` | `sledge_abi__current_wasm_module_instance.memory`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY` |
| memory.grow | `instruction_memory_grow` | | `sledge_abi__current_wasm_module_instance.memory`, `sledge_abi__wasm_memory_expand` |
| memory.size | `instruction_memory_size` | | `sledge_abi__current_wasm_module_instance.memory` |
| None | `initialize_region` | | `sledge_abi__current_wasm_module_instance.memory`, `sledge_abi__wasm_memory_initialize_region` |
# SLEdge \*.so Module Loading / Initialization
The `sledgert` runtime is invoked with an argument containing the path to a JSON file defining serverless functions. The JSON format is a top level array containing 0..N JSON objects with the following keys:
"name" - A Human friendly name identifying a serverless function. Is required.
"path" - A path to a \*.so module containing the program to be executed
"port" - The port which the serverless function is registered
"relative-deadline-us"
"expected-execution-us"
"admissions-percentile"
"http-resp-content-type"
The path to the JSON file is passed to `module_alloc_from_json`, which uses the Jasmine library to parse the JSON, performs validation, and passes the resulting specification to `module_alloc` for each module definition found. `module_alloc` allocated heap memory for a `struct module` and then calls `module_init`. `module_init` calls `sledge_abi_symbols_init`, which calls `dlopen` on the _.so file at the path specified in the JSON and then calls `dlsym` to resolve symbols within the _.so module.
- `module.abi.initialize_globals` -> `SLEDGE_ABI__INITIALIZE_GLOBALS` -> `populate_globals`
- `module.abi.initialize_memory`-> `SLEDGE_ABI__INITIALIZE_MEMORY` -> `populate_memory`
- `module.abi.initialize_table` -> `SLEDGE_ABI__INITIALIZE_TABLE` -> `populate_table`
- `module.abi.entrypoint` -> `SLEDGE_ABI__ENTRYPOINT` -> `wasmf__start`
- `module.abi.starting_pages` -> `SLEDGE_ABI__STARTING_PAGES` -> `starting_pages`
- `module.abi.max_pages` -> `SLEDGE_ABI__MAX_PAGES` -> `max_pages`
- `module.abi.globals_len` -> `SLEDGE_ABI__GLOBALS_LEN` -> `globals_len`
`module_init` then calls `module.abi.initialize_table`, which populates the indirect function table with the actual functions. This is performed once during module initialization because this table does not actually vary between instances of a module.
# SLEdge \*.so Module Instantiation
When `sledgert` receives a request at the registered port specified in the JSON, it performs allocation and initialization steps. The scheduler sets the expected ABI symbols and yields to `current_sandbox_start`, which immediately calls `current_sandbox_init`. This function initializes the associated runtime state and
1. calls `module.abi.initialize_globals` for the current sandbox if not NULL. This is optional because the module might not have been built with the `--runtime-globals`, in which case runtime globals are not used at all. If not NULL, the globals are set in the table.
2. calls `module.abi.initialize_memory`, which copies segments into the linear memory
`current_sandbox_init` calls `wasi_context_init` to initialize the WASI context within the runtime.
`current_sandbox_init` returns to `current_sandbox_start`, which sets up wasm traps using `setjmp` and then calls `module.abi.entrypoint`
# Discussion (follow-up with Github issues):
- Should `sledge_abi__current_wasm_module_instance` be turned into a macro defined int the ABI header? That way it'll be easier to change the ABI symbols (change once, applied everywhere).
- Should `instruction_memory_grow` be moved into sledgert? This would simplify the handling of the "cache" and generating a memory profile?
- Rename `sledge_abi__wasm_globals_*` to `sledge_abi__wasm_global_*`
- Implement Unsupported Numeric Instructions
- Should the wasm global table be accessed directly instead of via a runtime function? If we expose the wasm global table to libsledge, then we have worse ABI stability, but better performance.
- Should the Function Table be handled by the \*.so file or sledgert? Are function pointers really called that frequently?

@ -1,258 +0,0 @@
#pragma once
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <threads.h>
/* Do not include runtime headers here! */
/** ABI Types
* Changes to these types breaks the contract between sledgert and the *.so modules that it runs. This means that all
* modules must be recompiled. Avoid this!
*/
struct sledge_abi__wasm_table_entry {
uint32_t type_id;
void *func_pointer;
};
struct sledge_abi__wasm_table {
uint32_t length;
uint32_t capacity;
struct sledge_abi__wasm_table_entry *buffer; /* Backing heap allocation */
};
struct sledge_abi__wasm_memory {
uint64_t size; /* Initial Size in bytes */
uint64_t capacity; /* Size backed by actual pages */
uint64_t max; /* Soft cap in bytes. Defaults to 4GB */
uint8_t *buffer; /* Backing heap allocation. Different lifetime because realloc might move this */
};
/* 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
* entities https://webassembly.github.io/spec/core/exec/runtime.html#module-instances
*/
struct sledge_abi__wasm_module_instance {
uint64_t wasmg_0; /* Used to refer to the shadow stack */
struct sledge_abi__wasm_table *table;
/* Note: memory has an opaque type due to private state. Do not reorder members below this! */
struct sledge_abi__wasm_memory memory;
/* Private runtime state follows */
};
/* Based on example traps listed at https://webassembly.org/docs/security/ */
enum sledge_abi__wasm_trap
{
WASM_TRAP_INVALID_INDEX = 1,
WASM_TRAP_MISMATCHED_TYPE = 2,
WASM_TRAP_PROTECTED_CALL_STACK_OVERFLOW = 3,
WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY = 4,
WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION = 5,
WASM_TRAP_UNREACHABLE = 6,
WASM_TRAP_COUNT
};
/* Symbols expected from sledgert */
extern void sledge_abi__wasm_trap_raise(enum sledge_abi__wasm_trap trapno);
extern int32_t sledge_abi__wasm_memory_expand(struct sledge_abi__wasm_memory *wasm_memory, uint32_t page_count);
void sledge_abi__wasm_memory_initialize_region(struct sledge_abi__wasm_memory *wasm_memory, uint32_t offset,
uint32_t region_size, uint8_t region[]);
extern int32_t sledge_abi__wasm_globals_get_i32(uint32_t idx);
extern int64_t sledge_abi__wasm_globals_get_i64(uint32_t idx);
extern void sledge_abi__wasm_globals_set_i32(uint32_t idx, int32_t value, bool is_mutable);
extern void sledge_abi__wasm_globals_set_i64(uint32_t idx, int64_t value, bool is_mutable);
/* Wasm initialization functions generated by the aWsm compiler */
extern void sledge_abi__init_globals(void);
extern void sledge_abi__init_mem(void);
extern void sledge_abi__init_tbl(void);
extern int32_t sledge_abi__entrypoint(void);
extern uint32_t sledge_abi__wasm_memory_starting_pages(void);
extern uint32_t sledge_abi__wasm_memory_max_pages(void);
typedef void (*sledge_abi__init_globals_fn_t)(void);
#define SLEDGE_ABI__INITIALIZE_GLOBALS "sledge_abi__init_globals"
typedef void (*sledge_abi__init_mem_fn_t)(void);
#define SLEDGE_ABI__INITIALIZE_MEMORY "sledge_abi__init_mem"
typedef void (*sledge_abi__init_tbl_fn_t)(void);
#define SLEDGE_ABI__INITIALIZE_TABLE "sledge_abi__init_tbl"
typedef int32_t (*sledge_abi__entrypoint_fn_t)(void);
#define SLEDGE_ABI__ENTRYPOINT "sledge_abi__entrypoint"
typedef uint32_t (*sledge_abi__wasm_memory_starting_pages_fn_t)(void);
#define SLEDGE_ABI__STARTING_PAGES "sledge_abi__wasm_memory_starting_pages"
typedef uint32_t (*sledge_abi__wasm_memory_max_pages_fn_t)(void);
#define SLEDGE_ABI__MAX_PAGES "sledge_abi__wasm_memory_max_pages"
typedef uint32_t (*sledge_abi__wasm_memory_globals_len_fn_t)(void);
#define SLEDGE_ABI__GLOBALS_LEN "sledge_abi__wasm_globals_len"
typedef uint32_t __wasi_clockid_t;
typedef uint64_t __wasi_dircookie_t;
typedef uint32_t __wasi_exitcode_t;
typedef int32_t __wasi_fd_t;
typedef int64_t __wasi_filedelta_t;
typedef uint64_t __wasi_filesize_t;
typedef uint32_t __wasi_lookupflags_t;
typedef uint64_t __wasi_rights_t;
typedef uint32_t __wasi_size_t;
typedef uint64_t __wasi_timestamp_t;
#ifndef unlikely
#define unlikely(x) __builtin_expect(!!(x), 0)
#endif
#ifndef likely
#define likely(x) __builtin_expect(!!(x), 1)
#endif
uint32_t sledge_abi__wasi_snapshot_preview1_args_get(__wasi_size_t argv_retoffset, __wasi_size_t argv_buf_retoffset);
uint32_t
sledge_abi__wasi_snapshot_preview1_args_sizes_get(__wasi_size_t argc_retoffset, __wasi_size_t argv_buf_len_retoffset);
uint32_t sledge_abi__wasi_snapshot_preview1_clock_res_get(__wasi_clockid_t id, __wasi_size_t resolution_retoffset);
uint32_t sledge_abi__wasi_snapshot_preview1_clock_time_get(__wasi_clockid_t clock_id, __wasi_timestamp_t precision,
__wasi_size_t time_retoffset);
uint32_t sledge_abi__wasi_snapshot_preview1_environ_get(__wasi_size_t env_retoffset, __wasi_size_t env_buf_retoffset);
uint32_t
sledge_abi__wasi_snapshot_preview1_environ_sizes_get(__wasi_size_t envc_retoffset, __wasi_size_t env_buf_len_retoffset);
uint32_t sledge_abi__wasi_snapshot_preview1_fd_advise(__wasi_fd_t fd, __wasi_filesize_t file_offset,
__wasi_filesize_t len, uint32_t advice_extended);
uint32_t
sledge_abi__wasi_snapshot_preview1_fd_allocate(__wasi_fd_t fd, __wasi_filesize_t offset, __wasi_filesize_t len);
uint32_t sledge_abi__wasi_snapshot_preview1_fd_close(__wasi_fd_t fd);
uint32_t sledge_abi__wasi_snapshot_preview1_fd_datasync(__wasi_fd_t fd);
uint32_t sledge_abi__wasi_snapshot_preview1_fd_fdstat_get(__wasi_fd_t fd, __wasi_size_t fdstat_retoffset);
uint32_t sledge_abi__wasi_snapshot_preview1_fd_fdstat_set_flags(__wasi_fd_t fd, uint32_t fdflags_extended);
uint32_t sledge_abi__wasi_snapshot_preview1_fd_fdstat_set_rights(__wasi_fd_t fd, __wasi_rights_t fs_rights_base,
__wasi_rights_t fs_rights_inheriting);
uint32_t sledge_abi__wasi_snapshot_preview1_fd_filestat_get(__wasi_fd_t fd, __wasi_size_t filestat_retoffset);
uint32_t sledge_abi__wasi_snapshot_preview1_fd_filestat_set_size(__wasi_fd_t fd, __wasi_filesize_t size);
uint32_t sledge_abi__wasi_snapshot_preview1_fd_filestat_set_times(__wasi_fd_t fd, __wasi_timestamp_t atim,
__wasi_timestamp_t mtim, uint32_t fstflags_extended);
uint32_t
sledge_abi__wasi_snapshot_preview1_fd_pread(__wasi_fd_t fd, __wasi_size_t iovs_baseoffset, __wasi_size_t iovs_len,
__wasi_filesize_t offset, __wasi_size_t nread_retoffset);
uint32_t sledge_abi__wasi_snapshot_preview1_fd_prestat_get(__wasi_fd_t fd, __wasi_size_t prestat_retoffset);
uint32_t sledge_abi__wasi_snapshot_preview1_fd_prestat_dir_name(__wasi_fd_t fd, __wasi_size_t dirname_retoffset,
__wasi_size_t dirname_len);
uint32_t
sledge_abi__wasi_snapshot_preview1_fd_pwrite(__wasi_fd_t fd, __wasi_size_t iovs_baseoffset, __wasi_size_t iovs_len,
__wasi_filesize_t file_offset, __wasi_size_t nwritten_retoffset);
uint32_t sledge_abi__wasi_snapshot_preview1_fd_read(__wasi_fd_t fd, __wasi_size_t iovs_baseoffset,
__wasi_size_t iovs_len, __wasi_size_t nread_retoffset);
uint32_t
sledge_abi__wasi_snapshot_preview1_fd_readdir(__wasi_fd_t fd, __wasi_size_t buf_baseoffset, __wasi_size_t buf_len,
__wasi_dircookie_t cookie, __wasi_size_t nread_retoffset);
uint32_t sledge_abi__wasi_snapshot_preview1_fd_renumber(__wasi_fd_t fd, __wasi_fd_t to);
uint32_t sledge_abi__wasi_snapshot_preview1_fd_seek(__wasi_fd_t fd, __wasi_filedelta_t file_offset,
uint32_t whence_extended, __wasi_size_t newoffset_retoffset);
uint32_t sledge_abi__wasi_snapshot_preview1_fd_sync(__wasi_fd_t fd);
uint32_t sledge_abi__wasi_snapshot_preview1_fd_tell(__wasi_fd_t fd, __wasi_size_t fileoffset_retoffset);
uint32_t sledge_abi__wasi_snapshot_preview1_fd_write(__wasi_fd_t fd, __wasi_size_t iovs_baseoffset,
__wasi_size_t iovs_len, __wasi_size_t nwritten_retoffset);
uint32_t sledge_abi__wasi_snapshot_preview1_path_create_directory(__wasi_fd_t fd, __wasi_size_t path_baseoffset,
__wasi_size_t path_len);
uint32_t sledge_abi__wasi_snapshot_preview1_path_filestat_get(__wasi_fd_t fd, __wasi_lookupflags_t flags,
__wasi_size_t path_baseoffset, __wasi_size_t path_len,
__wasi_size_t filestat_retoffset);
uint32_t
sledge_abi__wasi_snapshot_preview1_path_filestat_set_times(__wasi_fd_t fd, __wasi_lookupflags_t flags,
__wasi_size_t path_baseoffset, __wasi_size_t path_len,
__wasi_timestamp_t atim, __wasi_timestamp_t mtim,
uint32_t fstflags_extended);
uint32_t sledge_abi__wasi_snapshot_preview1_path_link(__wasi_fd_t old_fd, __wasi_lookupflags_t old_flags,
__wasi_size_t old_path_baseoffset, __wasi_size_t old_path_len,
__wasi_fd_t new_fd, __wasi_size_t new_path_baseoffset,
__wasi_size_t new_path_len);
uint32_t sledge_abi__wasi_snapshot_preview1_path_open(__wasi_fd_t dirfd, __wasi_lookupflags_t lookupflags,
__wasi_size_t path_baseoffset, __wasi_size_t path_len,
uint32_t oflags_extended, __wasi_rights_t fs_rights_base,
__wasi_rights_t fs_rights_inheriting, uint32_t fdflags_extended,
__wasi_size_t fd_retoffset);
uint32_t sledge_abi__wasi_snapshot_preview1_path_readlink(__wasi_fd_t fd, __wasi_size_t path_baseoffset,
__wasi_size_t path_len, __wasi_size_t buf_baseretoffset,
__wasi_size_t buf_len, __wasi_size_t nread_retoffset);
uint32_t sledge_abi__wasi_snapshot_preview1_path_remove_directory(__wasi_fd_t fd, __wasi_size_t path_baseoffset,
__wasi_size_t path_len);
uint32_t sledge_abi__wasi_snapshot_preview1_path_rename(__wasi_fd_t fd, __wasi_size_t old_path_baseoffset,
__wasi_size_t old_path_len, __wasi_fd_t new_fd,
__wasi_size_t new_path_baseoffset, __wasi_size_t new_path_len);
uint32_t sledge_abi__wasi_snapshot_preview1_path_symlink(__wasi_size_t old_path_baseoffset, __wasi_size_t old_path_len,
__wasi_fd_t fd, __wasi_size_t new_path_baseoffset,
__wasi_size_t new_path_len);
uint32_t sledge_abi__wasi_snapshot_preview1_path_unlink_file(__wasi_fd_t fd, __wasi_size_t path_baseoffset,
__wasi_size_t path_len);
uint32_t sledge_abi__wasi_snapshot_preview1_poll_oneoff(__wasi_size_t in_baseoffset, __wasi_size_t out_baseoffset,
__wasi_size_t nsubscriptions, __wasi_size_t nevents_retoffset);
void sledge_abi__wasi_snapshot_preview1_proc_exit(__wasi_exitcode_t exitcode);
uint32_t sledge_abi__wasi_snapshot_preview1_proc_raise(uint32_t sig_extended);
uint32_t sledge_abi__wasi_snapshot_preview1_random_get(__wasi_size_t buf_baseretoffset, __wasi_size_t buf_len);
uint32_t sledge_abi__wasi_snapshot_preview1_sched_yield(void);
uint32_t sledge_abi__wasi_snapshot_preview1_sock_recv(__wasi_fd_t fd, __wasi_size_t ri_data_baseretoffset,
__wasi_size_t ri_data_len, uint32_t ri_flags_extended,
__wasi_size_t ri_data_nbytes_retoffset,
__wasi_size_t message_nbytes_retoffset);
uint32_t sledge_abi__wasi_snapshot_preview1_sock_send(__wasi_fd_t fd, __wasi_size_t si_data_baseoffset,
__wasi_size_t si_data_len, uint32_t si_flags_extended,
__wasi_size_t nbytes_retoffset);
uint32_t sledge_abi__wasi_snapshot_preview1_sock_shutdown(__wasi_fd_t fd, uint32_t how);
uint32_t sledge_abi__scratch_storage_get_size(uint32_t key_offset, uint32_t key_len);
int sledge_abi__scratch_storage_get(uint32_t key_offset, uint32_t key_size, uint32_t buf_offset, uint32_t buf_len);
int sledge_abi__scratch_storage_set(uint32_t key_offset, uint32_t key_len, uint32_t value_offset, uint32_t value_len);
int sledge_abi__scratch_storage_delete(uint32_t key_offset, uint32_t key_len);
void
sledge_abi__scratch_storage_upsert(uint32_t key_offset, uint32_t key_len, uint32_t value_offset, uint32_t value_len);

@ -1,7 +0,0 @@
#include "sledge_abi.h"
void
awsm_abi__trap_unreachable(void)
{
sledge_abi__wasm_trap_raise(WASM_TRAP_UNREACHABLE);
}

@ -1,67 +0,0 @@
#include "sledge_abi.h"
/* The visibility attribute is used to control the visibility of a symbol across C translation units. The default
* argument forces "external" linkage. This originated in gcc, but had been adopted by LLVM.
* Reference: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html */
#define EXPORT __attribute__((visibility("default")))
/* The weak attribute is used to provide a weak symbol that can be overridden by later linking to a "strong" symbol.
* This is useful for defining a default or no-op implementation of a symbol that might or might not be present in a
* binary. This applies to populate_globals() below, which is only generated by aWsm when a module is compiled with the
* "--runtime-globals" argument. We need to provide a weak symbol that does nothing to prevent unresolved symbols from
* triggering linker errors. */
#define WEAK __attribute__((weak))
/* aWsm ABI Symbols */
extern void populate_globals(void);
extern void populate_memory(void);
extern void populate_table(void);
extern void populate_table(void);
extern int32_t wasmf__start(void);
extern uint32_t starting_pages;
extern uint32_t max_pages;
extern uint32_t globals_len;
WEAK void populate_globals(){};
EXPORT void
sledge_abi__init_globals(void)
{
populate_globals();
}
void
sledge_abi__init_mem(void)
{
populate_memory();
}
EXPORT void
sledge_abi__init_tbl(void)
{
populate_table();
}
EXPORT int32_t
sledge_abi__entrypoint(void)
{
return wasmf__start();
}
EXPORT uint32_t
sledge_abi__wasm_memory_starting_pages(void)
{
return starting_pages;
}
EXPORT uint32_t
sledge_abi__wasm_memory_max_pages(void)
{
return max_pages;
}
EXPORT uint32_t
sledge_abi__wasm_globals_len(void)
{
return globals_len;
}

@ -1,133 +0,0 @@
#include "sledge_abi.h"
#define INLINE __attribute__((always_inline))
#define WASM_PAGE_SIZE (1024 * 64) /* 64KB */
/* This is private and NOT in the sledge_abi.h header because the runtime uses an overlay struct that extends this
* symbol with private members */
extern thread_local struct sledge_abi__wasm_module_instance sledge_abi__current_wasm_module_instance;
INLINE uint32_t
instruction_memory_size()
{
return (uint32_t)(sledge_abi__current_wasm_module_instance.memory.size / (uint64_t)WASM_PAGE_SIZE);
}
// These functions are equivalent to those in wasm_memory.h, but they minimize pointer dereferencing
INLINE float
get_f32(uint32_t offset)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
return *(float *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset];
}
INLINE double
get_f64(uint32_t offset)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
return *(double *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset];
}
INLINE int8_t
get_i8(uint32_t offset)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
return *(int8_t *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset];
}
INLINE int16_t
get_i16(uint32_t offset)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
return *(int16_t *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset];
}
INLINE int32_t
get_i32(uint32_t offset)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
return *(int32_t *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset];
}
INLINE int64_t
get_i64(uint32_t offset)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
return *(int64_t *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset];
}
// Now setting routines
INLINE void
set_f32(uint32_t offset, float value)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
*(float *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset] = value;
}
INLINE void
set_f64(uint32_t offset, double value)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
*(double *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset] = value;
}
INLINE void
set_i8(uint32_t offset, int8_t value)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
*(int8_t *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset] = value;
}
INLINE void
set_i16(uint32_t offset, int16_t value)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
*(int16_t *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset] = value;
}
INLINE void
set_i32(uint32_t offset, int32_t value)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
*(int32_t *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset] = value;
}
INLINE void
set_i64(uint32_t offset, int64_t value)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
*(int64_t *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset] = value;
}
/**
* @brief Stub that implements the WebAssembly memory.grow instruction
*
* @param count number of pages to grow the WebAssembly linear memory by
* @return The previous size of the linear memory in pages or -1 if enough memory cannot be allocated
*/
INLINE int32_t
instruction_memory_grow(uint32_t count)
{
return sledge_abi__wasm_memory_expand(&sledge_abi__current_wasm_module_instance.memory, count);
}
INLINE void
initialize_region(uint32_t offset, uint32_t region_size, uint8_t region[region_size])
{
sledge_abi__wasm_memory_initialize_region(&sledge_abi__current_wasm_module_instance.memory, offset, region_size,
region);
}

@ -1,65 +0,0 @@
#include <stdint.h>
#include "sledge_abi.h"
#define INLINE __attribute__((always_inline))
/**
* @param key
* @param key_len
* @returns value_size at key or 0 if key not present
*/
INLINE uint32_t
scratch_storage_get_size(uint32_t key_offset, uint32_t key_len)
{
return sledge_abi__scratch_storage_get_size(key_offset, key_len);
}
/**
* @param key_offset
* @param key_len
* @param buf_offset linear memory offset to buffer where value should be copied.
* @param buf_len Size of buffer. Assumed to be size returned by sledge_kv_get_value_size.
* @returns 0 on success, 1 if key missing, 2 if buffer too small
*/
INLINE int
scratch_storage_get(uint32_t key_offset, uint32_t key_len, uint32_t buf_offset, uint32_t buf_len)
{
return sledge_abi__scratch_storage_get(key_offset, key_len, buf_offset, buf_len);
};
/**
* @param key_offset
* @param key_len
* @param value_offset
* @param value_len
* @returns 0 on success, 1 if already present,
*/
INLINE int
scratch_storage_set(uint32_t key_offset, uint32_t key_len, uint32_t value_offset, uint32_t value_len)
{
return sledge_abi__scratch_storage_set(key_offset, key_len, value_offset, value_len);
}
/**
* @param key_offset
* @param key_len
* @returns 0 on success, 1 if not present
*/
INLINE int
scratch_storage_delete(uint32_t key_offset, uint32_t key_len)
{
return sledge_abi__scratch_storage_delete(key_offset, key_len);
}
/**
* @param key_offset
* @param key_len
* @param value_offset
* @param value_len
* @returns 0 on success, 1 if already present,
*/
INLINE void
scratch_storage_upsert(uint32_t key_offset, uint32_t key_len, uint32_t value_offset, uint32_t value_len)
{
sledge_abi__scratch_storage_upsert(key_offset, key_len, value_offset, value_len);
}

@ -1,60 +0,0 @@
#include "sledge_abi.h"
#define INDIRECT_TABLE_SIZE (1 << 10)
#define INLINE __attribute__((always_inline))
/* This is private and NOT in the sledge_abi.h header because the runtime uses an overlay struct that extends this
* symbol with private members */
extern thread_local struct sledge_abi__wasm_module_instance sledge_abi__current_wasm_module_instance;
static INLINE void *
wasm_table_get(struct sledge_abi__wasm_table *wasm_table, uint32_t idx, uint32_t type_id)
{
assert(wasm_table != NULL);
if (unlikely(idx >= wasm_table->capacity)) { sledge_abi__wasm_trap_raise(WASM_TRAP_INVALID_INDEX); }
struct sledge_abi__wasm_table_entry f = wasm_table->buffer[idx];
if (unlikely(f.type_id != type_id)) { sledge_abi__wasm_trap_raise(WASM_TRAP_MISMATCHED_TYPE); }
if (unlikely(f.func_pointer == NULL)) { sledge_abi__wasm_trap_raise(WASM_TRAP_MISMATCHED_TYPE); }
return f.func_pointer;
}
static INLINE void
wasm_table_set(struct sledge_abi__wasm_table *wasm_table, uint32_t idx, uint32_t type_id, char *pointer)
{
assert(wasm_table != NULL);
assert(idx < wasm_table->capacity);
assert(pointer != NULL);
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 };
}
INLINE void
add_function_to_table(uint32_t idx, uint32_t type_id, char *pointer)
{
wasm_table_set(sledge_abi__current_wasm_module_instance.table, idx, type_id, pointer);
}
/* char * is used as a generic pointer to a function pointer */
INLINE char *
get_function_from_table(uint32_t idx, uint32_t type_id)
{
assert(sledge_abi__current_wasm_module_instance.table != NULL);
if (unlikely(idx >= sledge_abi__current_wasm_module_instance.table->capacity)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_INVALID_INDEX);
}
struct sledge_abi__wasm_table_entry f = sledge_abi__current_wasm_module_instance.table->buffer[idx];
if (unlikely(f.type_id != type_id)) { sledge_abi__wasm_trap_raise(WASM_TRAP_MISMATCHED_TYPE); }
if (unlikely(f.func_pointer == NULL)) { sledge_abi__wasm_trap_raise(WASM_TRAP_MISMATCHED_TYPE); }
return f.func_pointer;
}

@ -1,52 +0,0 @@
#include <stdbool.h>
#include <stdint.h>
#include "sledge_abi.h"
/* This is private and NOT in the sledge_abi.h header because the runtime uses an overlay struct that extends this
* symbol with private members */
extern thread_local struct sledge_abi__wasm_module_instance sledge_abi__current_wasm_module_instance;
int32_t
get_global_i32(uint32_t idx)
{
if (idx == 0) {
return (int32_t)sledge_abi__current_wasm_module_instance.wasmg_0;
} else {
return sledge_abi__wasm_globals_get_i32(idx);
}
}
int64_t
get_global_i64(uint32_t idx)
{
if (idx == 0) {
return (int64_t)sledge_abi__current_wasm_module_instance.wasmg_0;
} else {
return sledge_abi__wasm_globals_get_i64(idx);
}
}
void
set_global_i32(uint32_t idx, int32_t value)
{
if (idx == 0) {
sledge_abi__current_wasm_module_instance.wasmg_0 = (uint64_t)value;
} else {
/* aWsm does not currently pass the is_mutable flag, so all runtime globals are assumed to be mutable.
This is true if aWsm uses the flags to inline constant globals */
sledge_abi__wasm_globals_set_i32(idx, value, true);
}
}
void
set_global_i64(uint32_t idx, int64_t value)
{
if (idx == 0) {
sledge_abi__current_wasm_module_instance.wasmg_0 = (uint64_t)value;
} else {
/* aWsm does not currently pass the is_mutable flag, so all runtime globals are assumed to be mutable.
This is true if aWsm uses the flags to inline constant globals */
sledge_abi__wasm_globals_set_i64(idx, value, true);
}
}

@ -1,311 +0,0 @@
#include <stdint.h>
#include "sledge_abi.h"
uint32_t
wasi_snapshot_preview1_args_get(__wasi_size_t argv_retoffset, __wasi_size_t argv_buf_retoffset)
{
return sledge_abi__wasi_snapshot_preview1_args_get(argv_retoffset, argv_buf_retoffset);
}
uint32_t
wasi_snapshot_preview1_args_sizes_get(__wasi_size_t argc_retoffset, __wasi_size_t argv_buf_len_retoffset)
{
return sledge_abi__wasi_snapshot_preview1_args_sizes_get(argc_retoffset, argv_buf_len_retoffset);
};
uint32_t
wasi_snapshot_preview1_clock_res_get(__wasi_clockid_t id, __wasi_size_t resolution_retoffset)
{
return sledge_abi__wasi_snapshot_preview1_clock_res_get(id, resolution_retoffset);
}
uint32_t
wasi_snapshot_preview1_clock_time_get(__wasi_clockid_t clock_id, __wasi_timestamp_t precision,
__wasi_size_t time_retoffset)
{
return sledge_abi__wasi_snapshot_preview1_clock_time_get(clock_id, precision, time_retoffset);
}
uint32_t
wasi_snapshot_preview1_environ_get(__wasi_size_t env_retoffset, __wasi_size_t env_buf_retoffset)
{
return sledge_abi__wasi_snapshot_preview1_environ_get(env_retoffset, env_buf_retoffset);
}
uint32_t
wasi_snapshot_preview1_environ_sizes_get(__wasi_size_t envc_retoffset, __wasi_size_t env_buf_len_retoffset)
{
return sledge_abi__wasi_snapshot_preview1_environ_sizes_get(envc_retoffset, env_buf_len_retoffset);
}
uint32_t
wasi_snapshot_preview1_fd_advise(__wasi_fd_t fd, __wasi_filesize_t file_offset, __wasi_filesize_t len,
uint32_t advice_extended)
{
return sledge_abi__wasi_snapshot_preview1_fd_advise(fd, file_offset, len, advice_extended);
}
uint32_t
wasi_snapshot_preview1_fd_allocate(__wasi_fd_t fd, __wasi_filesize_t offset, __wasi_filesize_t len)
{
return sledge_abi__wasi_snapshot_preview1_fd_allocate(fd, offset, len);
}
uint32_t
wasi_snapshot_preview1_fd_close(__wasi_fd_t fd)
{
return sledge_abi__wasi_snapshot_preview1_fd_close(fd);
}
uint32_t
wasi_snapshot_preview1_fd_datasync(__wasi_fd_t fd)
{
return sledge_abi__wasi_snapshot_preview1_fd_datasync(fd);
}
uint32_t
wasi_snapshot_preview1_fd_fdstat_get(__wasi_fd_t fd, __wasi_size_t fdstat_retoffset)
{
return sledge_abi__wasi_snapshot_preview1_fd_fdstat_get(fd, fdstat_retoffset);
}
uint32_t
wasi_snapshot_preview1_fd_fdstat_set_flags(__wasi_fd_t fd, uint32_t fdflags_extended)
{
return sledge_abi__wasi_snapshot_preview1_fd_fdstat_set_flags(fd, fdflags_extended);
}
uint32_t
wasi_snapshot_preview1_fd_fdstat_set_rights(__wasi_fd_t fd, __wasi_rights_t fs_rights_base,
__wasi_rights_t fs_rights_inheriting)
{
return sledge_abi__wasi_snapshot_preview1_fd_fdstat_set_rights(fd, fs_rights_base, fs_rights_inheriting);
}
uint32_t
wasi_snapshot_preview1_fd_filestat_get(__wasi_fd_t fd, __wasi_size_t filestat_retoffset)
{
return sledge_abi__wasi_snapshot_preview1_fd_filestat_get(fd, filestat_retoffset);
}
uint32_t
wasi_snapshot_preview1_fd_filestat_set_size(__wasi_fd_t fd, __wasi_filesize_t size)
{
return sledge_abi__wasi_snapshot_preview1_fd_filestat_set_size(fd, size);
}
uint32_t
wasi_snapshot_preview1_fd_filestat_set_times(__wasi_fd_t fd, __wasi_timestamp_t atim, __wasi_timestamp_t mtim,
uint32_t fstflags_extended)
{
return sledge_abi__wasi_snapshot_preview1_fd_filestat_set_times(fd, atim, mtim, fstflags_extended);
}
uint32_t
wasi_snapshot_preview1_fd_pread(__wasi_fd_t fd, __wasi_size_t iovs_baseoffset, __wasi_size_t iovs_len,
__wasi_filesize_t offset, __wasi_size_t nread_retoffset)
{
return sledge_abi__wasi_snapshot_preview1_fd_pread(fd, iovs_baseoffset, iovs_len, offset, nread_retoffset);
}
uint32_t
wasi_snapshot_preview1_fd_prestat_get(__wasi_fd_t fd, __wasi_size_t prestat_retoffset)
{
return sledge_abi__wasi_snapshot_preview1_fd_prestat_get(fd, prestat_retoffset);
}
uint32_t
wasi_snapshot_preview1_fd_prestat_dir_name(__wasi_fd_t fd, __wasi_size_t dirname_retoffset, __wasi_size_t dirname_len)
{
return sledge_abi__wasi_snapshot_preview1_fd_prestat_dir_name(fd, dirname_retoffset, dirname_len);
}
uint32_t
wasi_snapshot_preview1_fd_pwrite(__wasi_fd_t fd, __wasi_size_t iovs_baseoffset, __wasi_size_t iovs_len,
__wasi_filesize_t file_offset, __wasi_size_t nwritten_retoffset)
{
return sledge_abi__wasi_snapshot_preview1_fd_pwrite(fd, iovs_baseoffset, iovs_len, file_offset,
nwritten_retoffset);
}
uint32_t
wasi_snapshot_preview1_fd_read(__wasi_fd_t fd, __wasi_size_t iovs_baseoffset, __wasi_size_t iovs_len,
__wasi_size_t nread_retoffset)
{
return sledge_abi__wasi_snapshot_preview1_fd_read(fd, iovs_baseoffset, iovs_len, nread_retoffset);
}
uint32_t
wasi_snapshot_preview1_fd_readdir(__wasi_fd_t fd, __wasi_size_t buf_baseoffset, __wasi_size_t buf_len,
__wasi_dircookie_t cookie, __wasi_size_t nread_retoffset)
{
return sledge_abi__wasi_snapshot_preview1_fd_readdir(fd, buf_baseoffset, buf_len, cookie, nread_retoffset);
}
uint32_t
wasi_snapshot_preview1_fd_renumber(__wasi_fd_t fd, __wasi_fd_t to)
{
return sledge_abi__wasi_snapshot_preview1_fd_renumber(fd, to);
}
uint32_t
wasi_snapshot_preview1_fd_seek(__wasi_fd_t fd, __wasi_filedelta_t file_offset, uint32_t whence_extended,
__wasi_size_t newoffset_retoffset)
{
return sledge_abi__wasi_snapshot_preview1_fd_seek(fd, file_offset, whence_extended, newoffset_retoffset);
}
uint32_t
wasi_snapshot_preview1_fd_sync(__wasi_fd_t fd)
{
return sledge_abi__wasi_snapshot_preview1_fd_sync(fd);
}
uint32_t
wasi_snapshot_preview1_fd_tell(__wasi_fd_t fd, __wasi_size_t fileoffset_retoffset)
{
return sledge_abi__wasi_snapshot_preview1_fd_tell(fd, fileoffset_retoffset);
}
uint32_t
wasi_snapshot_preview1_fd_write(__wasi_fd_t fd, __wasi_size_t iovs_baseoffset, __wasi_size_t iovs_len,
__wasi_size_t nwritten_retoffset)
{
return sledge_abi__wasi_snapshot_preview1_fd_write(fd, iovs_baseoffset, iovs_len, nwritten_retoffset);
}
uint32_t
wasi_snapshot_preview1_path_create_directory(__wasi_fd_t fd, __wasi_size_t path_baseoffset, __wasi_size_t path_len)
{
return sledge_abi__wasi_snapshot_preview1_path_create_directory(fd, path_baseoffset, path_len);
}
uint32_t
wasi_snapshot_preview1_path_filestat_get(__wasi_fd_t fd, __wasi_lookupflags_t flags, __wasi_size_t path_baseoffset,
__wasi_size_t path_len, __wasi_size_t filestat_retoffset)
{
return sledge_abi__wasi_snapshot_preview1_path_filestat_get(fd, flags, path_baseoffset, path_len,
filestat_retoffset);
}
uint32_t
wasi_snapshot_preview1_path_filestat_set_times(__wasi_fd_t fd, __wasi_lookupflags_t flags,
__wasi_size_t path_baseoffset, __wasi_size_t path_len,
__wasi_timestamp_t atim, __wasi_timestamp_t mtim,
uint32_t fstflags_extended)
{
return sledge_abi__wasi_snapshot_preview1_path_filestat_set_times(fd, flags, path_baseoffset, path_len, atim,
mtim, fstflags_extended);
}
uint32_t
wasi_snapshot_preview1_path_link(__wasi_fd_t old_fd, __wasi_lookupflags_t old_flags, __wasi_size_t old_path_baseoffset,
__wasi_size_t old_path_len, __wasi_fd_t new_fd, __wasi_size_t new_path_baseoffset,
__wasi_size_t new_path_len)
{
return sledge_abi__wasi_snapshot_preview1_path_link(old_fd, old_flags, old_path_baseoffset, old_path_len,
new_fd, new_path_baseoffset, new_path_len);
}
uint32_t
wasi_snapshot_preview1_path_open(__wasi_fd_t dirfd, __wasi_lookupflags_t lookupflags, __wasi_size_t path_baseoffset,
__wasi_size_t path_len, uint32_t oflags_extended, __wasi_rights_t fs_rights_base,
__wasi_rights_t fs_rights_inheriting, uint32_t fdflags_extended,
__wasi_size_t fd_retoffset)
{
return sledge_abi__wasi_snapshot_preview1_path_open(dirfd, lookupflags, path_baseoffset, path_len,
oflags_extended, fs_rights_base, fs_rights_inheriting,
fdflags_extended, fd_retoffset);
}
uint32_t
wasi_snapshot_preview1_path_readlink(__wasi_fd_t fd, __wasi_size_t path_baseoffset, __wasi_size_t path_len,
__wasi_size_t buf_baseretoffset, __wasi_size_t buf_len,
__wasi_size_t nread_retoffset)
{
return sledge_abi__wasi_snapshot_preview1_path_readlink(fd, path_baseoffset, path_len, buf_baseretoffset,
buf_len, nread_retoffset);
}
uint32_t
wasi_snapshot_preview1_path_remove_directory(__wasi_fd_t fd, __wasi_size_t path_baseoffset, __wasi_size_t path_len)
{
return sledge_abi__wasi_snapshot_preview1_path_remove_directory(fd, path_baseoffset, path_len);
}
uint32_t
wasi_snapshot_preview1_path_rename(__wasi_fd_t fd, __wasi_size_t old_path_baseoffset, __wasi_size_t old_path_len,
__wasi_fd_t new_fd, __wasi_size_t new_path_baseoffset, __wasi_size_t new_path_len)
{
return sledge_abi__wasi_snapshot_preview1_path_rename(fd, old_path_baseoffset, old_path_len, new_fd,
new_path_baseoffset, new_path_len);
}
uint32_t
wasi_snapshot_preview1_path_symlink(__wasi_size_t old_path_baseoffset, __wasi_size_t old_path_len, __wasi_fd_t fd,
__wasi_size_t new_path_baseoffset, __wasi_size_t new_path_len)
{
return sledge_abi__wasi_snapshot_preview1_path_symlink(old_path_baseoffset, old_path_len, fd,
new_path_baseoffset, new_path_len);
}
uint32_t
wasi_snapshot_preview1_path_unlink_file(__wasi_fd_t fd, __wasi_size_t path_baseoffset, __wasi_size_t path_len)
{
return sledge_abi__wasi_snapshot_preview1_path_unlink_file(fd, path_baseoffset, path_len);
}
uint32_t
wasi_snapshot_preview1_poll_oneoff(__wasi_size_t in_baseoffset, __wasi_size_t out_baseoffset,
__wasi_size_t nsubscriptions, __wasi_size_t nevents_retoffset)
{
return sledge_abi__wasi_snapshot_preview1_poll_oneoff(in_baseoffset, out_baseoffset, nsubscriptions,
nevents_retoffset);
}
void
wasi_snapshot_preview1_proc_exit(__wasi_exitcode_t exitcode)
{
sledge_abi__wasi_snapshot_preview1_proc_exit(exitcode);
}
uint32_t
wasi_snapshot_preview1_proc_raise(uint32_t sig_extended)
{
return sledge_abi__wasi_snapshot_preview1_proc_raise(sig_extended);
}
uint32_t
wasi_snapshot_preview1_random_get(__wasi_size_t buf_baseretoffset, __wasi_size_t buf_len)
{
return sledge_abi__wasi_snapshot_preview1_random_get(buf_baseretoffset, buf_len);
}
uint32_t
wasi_snapshot_preview1_sched_yield(void)
{
return sledge_abi__wasi_snapshot_preview1_sched_yield();
}
uint32_t
wasi_snapshot_preview1_sock_recv(__wasi_fd_t fd, __wasi_size_t ri_data_baseretoffset, __wasi_size_t ri_data_len,
uint32_t ri_flags_extended, __wasi_size_t ri_data_nbytes_retoffset,
__wasi_size_t message_nbytes_retoffset)
{
return sledge_abi__wasi_snapshot_preview1_sock_recv(fd, ri_data_baseretoffset, ri_data_len, ri_flags_extended,
ri_data_nbytes_retoffset, message_nbytes_retoffset);
}
uint32_t
wasi_snapshot_preview1_sock_send(__wasi_fd_t fd, __wasi_size_t si_data_baseoffset, __wasi_size_t si_data_len,
uint32_t si_flags_extended, __wasi_size_t nbytes_retoffset)
{
return sledge_abi__wasi_snapshot_preview1_sock_send(fd, si_data_baseoffset, si_data_len, si_flags_extended,
nbytes_retoffset);
}
uint32_t
wasi_snapshot_preview1_sock_shutdown(__wasi_fd_t fd, uint32_t how)
{
return sledge_abi__wasi_snapshot_preview1_sock_shutdown(fd, how);
}

@ -11,48 +11,37 @@ CFLAGS=-std=c18 -pthread
# We use several non-standard glibc / Linux features:
# sched_getcpu, MAP_ANONYMOUS, acceess to 'gregs' in 'mcontext_t', REG_RIP, REG_RSP
CFLAGS+=-D_GNU_SOURCE
CFLAGS+=-D_GNU_SOURCE
# Release Flags
CFLAGS+=-O3 -flto
# Debugging Flags
# CFLAGS+=-O0 -g3
# CFLAGS+=-O0 -g
# CFI Sanitizer
# CFLAGS+=-fvisibility=default -fsanitize=cfi
# CFLAGS+=-O0 -g -flto -fvisibility=default -fsanitize=cfi
# Undefined Sanitizer - https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
# CFLAGS+=-fsanitize=undefined,float-divide-by-zero,unsigned-integer-overflow,implicit-conversion,local-bounds,nullability
# Undefined Sanitizer
# CFLAGS+=-O0 -g -fsanitize=undefined,float-divide-by-zero,unsigned-integer-overflow,implicit-conversion,local-bounds
# Clang SafeStack - https://clang.llvm.org/docs/SafeStack.html
# CFLAGS+=-fsanitize=safe-stack
# CFLAGS+=-O0 -g -fsanitize=safe-stack
# Memory Sanitizer - https://clang.llvm.org/docs/MemorySanitizer.html
# CFLAGS+=-fsanitize=memory -fno-omit-frame-pointer
# CFLAGS+=-O0 -g -fsanitize=memory -fno-omit-frame-pointer
# Address Sanitizer - "Fast Memory Error Detector" - https://clang.llvm.org/docs/AddressSanitizer.html
# CFLAGS+=-fsanitize=address -fno-omit-frame-pointer
# Address Sanitizer - https://clang.llvm.org/docs/AddressSanitizer.html
# CFLAGS+=-O0 -g -fsanitize=address -fno-omit-frame-pointer
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
# Enables logs of WASI syscalls
# CFLAGS += -DLOG_WASI
# Sandbox writes to stdout and stderr are both written to the client socket
# However, when set, stderr is also written to the host stderr to assist with debugging
# CFLAGS += -DLOG_SANDBOX_STDERR
# Strips out calls to assert() and disables debuglog
# CFLAGS += -DNDEBUG
@ -60,46 +49,34 @@ 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
# CFLAGS += -DLOG_TENANT_LOADING
# CFLAGS += -DLOG_LOCK_OVERHEAD
# CFLAGS += -DLOG_CONTEXT_SWITCHES
# CFLAGS += -DLOG_ADMISSIONS_CONTROL
# CFLAGS += -DLOG_REQUEST_ALLOCATION
# CFLAGS += -DLOG_PREEMPTION
# CFLAGS += -DLOG_SANDBOX_ALLOCATION
# CFLAGS += -DLOG_UNSUPPORTED_WASI
# Stores and logs extended signal information for each worker
# CFLAGS += -DLOG_SOFTWARE_INTERRUPT_COUNTS
# CFLAGS += -DLOG_MODULE_LOADING
# This adds an array of sandbox states to all sandbox structs and appends states at each transition
# The history trucates when the number of elements equal SANDBOX_STATE_HISTORY_CAPACITY
# CFLAGS += -DLOG_STATE_CHANGES
# Stores the max number of deferred SIGALRMS for each worker
# CFLAGS += -DLOG_DEFERRED_SIGALRM_MAX
# This dumps per module *.csv files containing the cycle a sandbox has been in RUNNING when each
# page is allocated. This helps understand the relationship to memory allocation and execution time.
# CFLAGS += -DLOG_SANDBOX_MEMORY_PROFILE
# This flag enables runtime-level metrics from procfs
# CFLAGS += -DPROC_STAT_METRICS
# This flag enables HTTP-level counters of incoming requests and outgoing responses, broken out by status code
# family, such as 2XX, 4XX, 5XX.
# This flag dumps totals of incoming requests and outgoing responses, broken out by status code
# family, such as 2XX, 4XX, 5XX. It is useful to debug clients hanging waiting for a response.
# To log, run `call http_total_log()` while in GDB
# CFLAGS += -DHTTP_TOTAL_COUNTERS
# This flag enables per-route counters of incoming requests and outgoing responses, broken out by status code
# family, such as 2XX, 4XX, 5XX.
# CFLAGS += -DHTTP_ROUTE_TOTAL_COUNTERS
# This flag enables per-route latency perf-logs.
# This has a perf impact due to the use of locks.
# This flag has a dependency on the flag HTTP_ROUTE_TOTAL_COUNTERS
# CFLAGS += -DROUTE_LATENCY
# CFLAGS += -DLOG_TOTAL_REQS_RESPS
# This flag tracks the total number of sandboxes in the various states
# This flag logs 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
# To log, run `call runtime_log_sandbox_states()` while in GDB
# CFLAGS += -DLOG_SANDBOX_COUNT
# 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
@ -110,6 +87,7 @@ CFLAGS += -DEXECUTION_HISTOGRAM
# Sets a flag equal to the processor architecture
CFLAGS += -D${ARCH}
# Preprocessor
# SLEdge serverless functions are *.so shared-libraries. The runtime thus requires the dynamic linker
@ -121,50 +99,49 @@ LDFLAGS += -Wl,--export-dynamic -ldl -lm
# Our third-party dependencies build into a single dist directory to simplify configuration here.
LDFLAGS += -Lthirdparty/dist/lib/
INCLUDES += -Iinclude/ -Ithirdparty/dist/include/ -I../libsledge/include/
INCLUDES += -Iinclude/ -Ithirdparty/dist/include/
# CFILES
CFILES += src/*.c
CFILES += src/arch/${ARCH}/*.c
CFILES += src/libc/*.c
CFILES += src/memory/common.c
CFILES += src/memory/64bit_nix.c
CFILES += thirdparty/dist/lib/http_parser.o
# Configuring Jasmine
JSMNCFLAGS += -DJSMN_STATIC
JSMNCFLAGS += -DJSMN_STRICT
# Force sledgert to rebuild when header files change
# This is a bit fragile, as it does not recurse subdirectories when detecting last changed times
HEADER_DEPS = thirdparty/dist/include/*.h include/*.h include/arch/x86_64/*.h include/arch/aarch64/*.h
.PHONY: all
all: thirdparty runtime
.PHONY: clean
clean: thirdparty.clean runtime.clean
all: runtime
# sledgert Rules
bin/${BINARY_NAME}: ${HEADER_DEPS} ${CFILES}
bin/sledgert: ${CFILES}
@echo "Compiling runtime"
@mkdir -p bin/
@${CC} ${INCLUDES} ${CFLAGS} ${LDFLAGS} ${JSMNCFLAGS} -L/usr/lib/ ${CFILES} -o bin/${BINARY_NAME}
${CC} ${INCLUDES} ${CFLAGS} ${LDFLAGS} ${JSMNCFLAGS} -L/usr/lib/ $^ -o bin/sledgert
.PHONY: runtime
runtime: bin/${BINARY_NAME}
.PHONY: runtime.clean
runtime.clean:
@rm -f bin/${BINARY_NAME}
# Thirdparty Dependency Rules
thirdparty/dist/lib/http_parser.o: thirdparty
thirdparty/dist/include/*.h: thirdparty
runtime: thirdparty bin/sledgert
.PHONY: thirdparty
thirdparty:
@echo "Compiling thirdparty"
@make --no-print-directory -C thirdparty build
.PHONY: thirdparty.clean
thirdparty.clean:
.PHONY: clean
clean:
@rm -f core
@echo "Cleaning up runtime"
@rm -f bin/${BINARY_NAME}
.PHONY: distclean
distclean: clean
@make --no-print-directory -C thirdparty clean
.PHONY: submodules
submodules:
@git submodule update --init --recursive
.PHONY: init
init: submodules clean thirdparty runtime

@ -1,9 +1,12 @@
#include <limits.h>
#include <assert.h>
#include <math.h>
#include <types.h>
#include "sledge_abi.h"
#define CHAR_BIT 8
#define INLINE __attribute__((always_inline))
// TODO: Throughout here we use `assert` for error conditions, which isn't optimal
// Instead we should use `unlikely` branches to a single trapping function (which should optimize better)
// The below functions are for implementing WASM instructions
// ROTL and ROTR helper functions
INLINE uint32_t
@ -54,48 +57,56 @@ rotr_u64(uint64_t n, uint64_t c_u64)
INLINE uint32_t
u32_div(uint32_t a, uint32_t b)
{
assert(b);
return a / b;
}
INLINE uint32_t
u32_rem(uint32_t a, uint32_t b)
{
assert(b);
return a % b;
}
INLINE int32_t
i32_div(int32_t a, int32_t b)
{
assert(b && (a != INT32_MIN || b != -1));
return a / b;
}
INLINE int32_t
i32_rem(int32_t a, int32_t b)
{
assert(b && (a != INT32_MIN || b != -1));
return a % b;
}
INLINE uint64_t
u64_div(uint64_t a, uint64_t b)
{
assert(b);
return a / b;
}
INLINE uint64_t
u64_rem(uint64_t a, uint64_t b)
{
assert(b);
return a % b;
}
INLINE int64_t
i64_div(int64_t a, int64_t b)
{
assert(b && (a != INT64_MIN || b != -1));
return a / b;
}
INLINE int64_t
i64_rem(int64_t a, int64_t b)
{
assert(b && (a != INT64_MIN || b != -1));
return a % b;
}
@ -105,71 +116,64 @@ i64_rem(int64_t a, int64_t b)
uint32_t
u32_trunc_f32(float f)
{
if (unlikely(f < 0 || f > (float)UINT32_MAX))
sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
assert(0 <= f && f <= (float)UINT32_MAX);
return (uint32_t)f;
}
int32_t
i32_trunc_f32(float f)
{
if (unlikely(f < INT32_MIN || f > (float)INT32_MAX))
sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
assert(INT32_MIN <= f && f <= (float)INT32_MAX);
return (int32_t)f;
}
uint32_t
u32_trunc_f64(double f)
{
if (unlikely(f < 0 || f > (double)UINT32_MAX))
sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
assert(0 <= f && f <= (double)UINT32_MAX);
return (uint32_t)f;
}
int32_t
i32_trunc_f64(double f)
{
if (unlikely(f < (double)INT32_MIN || f > (double)INT32_MAX))
sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
assert(INT32_MIN <= f && f <= (double)INT32_MAX);
return (int32_t)f;
}
uint64_t
u64_trunc_f32(float f)
{
if (unlikely(f < 0 || f > (float)UINT64_MAX))
sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
assert(0 <= f && f <= (float)UINT64_MAX);
return (uint64_t)f;
}
int64_t
i64_trunc_f32(float f)
{
if (unlikely(f < (float)INT64_MIN || f > (float)INT64_MAX))
sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
assert(INT64_MIN <= f && f <= (float)INT64_MAX);
return (int64_t)f;
}
uint64_t
u64_trunc_f64(double f)
{
if (unlikely(f < 0 || f > (float)UINT64_MAX))
sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
assert(0 <= f && f <= (double)UINT64_MAX);
return (uint64_t)f;
}
int64_t
i64_trunc_f64(double f)
{
if (unlikely(f < (double)INT64_MIN || f > (double)INT64_MAX))
sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
assert(INT64_MIN <= f && f <= (double)INT64_MAX);
return (int64_t)f;
}
// Float => Float truncation functions
INLINE float
f32_trunc_f32(float f)
{
return truncf(f);
return trunc(f);
}
INLINE float
@ -187,31 +191,7 @@ f32_max(float a, float b)
INLINE float
f32_floor(float a)
{
return floorf(a);
}
INLINE float
f32_ceil(float a)
{
return ceilf(a);
}
INLINE float
f32_copysign(float a, float b)
{
return copysignf(a, b);
}
INLINE float
f32_nearest(float a)
{
return nearbyintf(a);
}
INLINE double
f64_trunc_f64(double f)
{
return trunc(f);
return floor(a);
}
INLINE double
@ -231,21 +211,3 @@ f64_floor(double a)
{
return floor(a);
}
INLINE double
f64_ceil(double a)
{
return ceil(a);
}
INLINE double
f64_copysign(double a, double b)
{
return copysign(a, b);
}
INLINE double
f64_nearest(double a)
{
return nearbyint(a);
}

@ -0,0 +1,182 @@
#include <assert.h>
#include "types.h"
uint32_t
instruction_memory_size()
{
return local_sandbox_context_cache.memory.size / WASM_PAGE_SIZE;
}
// All of these are pretty generic
INLINE float
get_f32(uint32_t offset)
{
assert(offset + sizeof(float) <= local_sandbox_context_cache.memory.size);
char *mem_as_chars = (char *)local_sandbox_context_cache.memory.start;
void *address = &mem_as_chars[offset];
return *(float *)address;
}
INLINE double
get_f64(uint32_t offset)
{
assert(offset + sizeof(double) <= local_sandbox_context_cache.memory.size);
char *mem_as_chars = (char *)local_sandbox_context_cache.memory.start;
void *address = &mem_as_chars[offset];
return *(double *)address;
}
INLINE int8_t
get_i8(uint32_t offset)
{
assert(offset + sizeof(int8_t) <= local_sandbox_context_cache.memory.size);
char *mem_as_chars = (char *)local_sandbox_context_cache.memory.start;
void *address = &mem_as_chars[offset];
return *(int8_t *)address;
}
INLINE int16_t
get_i16(uint32_t offset)
{
assert(offset + sizeof(int16_t) <= local_sandbox_context_cache.memory.size);
char *mem_as_chars = (char *)local_sandbox_context_cache.memory.start;
void *address = &mem_as_chars[offset];
return *(int16_t *)address;
}
INLINE int32_t
get_i32(uint32_t offset)
{
assert(offset + sizeof(int32_t) <= local_sandbox_context_cache.memory.size);
char *mem_as_chars = (char *)local_sandbox_context_cache.memory.start;
void *address = &mem_as_chars[offset];
return *(int32_t *)address;
}
INLINE int64_t
get_i64(uint32_t offset)
{
assert(offset + sizeof(int64_t) <= local_sandbox_context_cache.memory.size);
char *mem_as_chars = (char *)local_sandbox_context_cache.memory.start;
void *address = &mem_as_chars[offset];
return *(int64_t *)address;
}
INLINE int32_t
get_global_i32(uint32_t offset)
{
return get_i32(offset);
}
INLINE int64_t
get_global_i64(uint32_t offset)
{
return get_i64(offset);
}
// Now setting routines
INLINE void
set_f32(uint32_t offset, float v)
{
assert(offset + sizeof(float) <= local_sandbox_context_cache.memory.size);
char *mem_as_chars = (char *)local_sandbox_context_cache.memory.start;
void *address = &mem_as_chars[offset];
*(float *)address = v;
}
INLINE void
set_f64(uint32_t offset, double v)
{
assert(offset + sizeof(double) <= local_sandbox_context_cache.memory.size);
char *mem_as_chars = (char *)local_sandbox_context_cache.memory.start;
void *address = &mem_as_chars[offset];
*(double *)address = v;
}
INLINE void
set_i8(uint32_t offset, int8_t v)
{
assert(offset + sizeof(int8_t) <= local_sandbox_context_cache.memory.size);
char *mem_as_chars = (char *)local_sandbox_context_cache.memory.start;
void *address = &mem_as_chars[offset];
*(int8_t *)address = v;
}
INLINE void
set_i16(uint32_t offset, int16_t v)
{
assert(offset + sizeof(int16_t) <= local_sandbox_context_cache.memory.size);
char *mem_as_chars = (char *)local_sandbox_context_cache.memory.start;
void *address = &mem_as_chars[offset];
*(int16_t *)address = v;
}
INLINE void
set_i32(uint32_t offset, int32_t v)
{
assert(offset + sizeof(int32_t) <= local_sandbox_context_cache.memory.size);
char *mem_as_chars = (char *)local_sandbox_context_cache.memory.start;
void *address = &mem_as_chars[offset];
*(int32_t *)address = v;
}
INLINE void
set_i64(uint32_t offset, int64_t v)
{
assert(offset + sizeof(int64_t) <= local_sandbox_context_cache.memory.size);
char *mem_as_chars = (char *)local_sandbox_context_cache.memory.start;
void *address = &mem_as_chars[offset];
*(int64_t *)address = v;
}
INLINE void
set_global_i32(uint32_t offset, int32_t v)
{
set_i32(offset, v);
}
INLINE void
set_global_i64(uint32_t offset, int64_t v)
{
set_i64(offset, v);
}
// Table handling functionality
// INLINE char *
// get_function_from_table(uint32_t idx, uint32_t type_id)
// {
// assert(idx < INDIRECT_TABLE_SIZE);
// struct indirect_table_entry f = local_sandbox_context_cache.module_indirect_table[idx];
// // FIXME: Commented out function type check because of gocr
// // assert(f.type_id == type_id);
// assert(f.func_pointer);
// return f.func_pointer;
// }

@ -0,0 +1,4 @@
*res.dat
rt.log
log.csv
res/*

@ -8,7 +8,7 @@ The `rust.sh` script stores per-run results to temporary files suffixed with `*.
In order to be compatible with the stdin/stdout model of serverless, the input and output files are binary concatenations of various C structs.
See `main()` in `applications/TinyEKF/extras/c/gps_ekf_fn.c` for specifics.
See `main()` in `runtime/tests/TinyEKF/extras/c/gps_ekf_fn.c` for specifics.
## Useful parsing of the log

@ -0,0 +1,3 @@
SLEDGE_SCHEDULER=EDF
SLEDGE_DISABLE_PREEMPTION=false
SLEDGE_SIGALRM_HANDLER=TRIAGED

@ -2,7 +2,7 @@
# Add bash_libraries directory to path
__run_sh__base_path="$(dirname "$(realpath --logical "${BASH_SOURCE[0]}")")"
__run_sh__bash_libraries_relative_path="../../bash_libraries"
__run_sh__bash_libraries_relative_path="../../../bash_libraries"
__run_sh__bash_libraries_absolute_path=$(cd "$__run_sh__base_path" && cd "$__run_sh__bash_libraries_relative_path" && pwd)
export PATH="$__run_sh__bash_libraries_absolute_path:$PATH"
@ -21,16 +21,19 @@ run_functional_tests() {
local -ir total_count=50
local tmpfs_dir=/tmp/sledge_ekf_by_iteration
rm -rf "$tmpfs_dir"
[[ -d "$tmpfs_dir" ]] && {
echo "$tmpfs_dir directory exists. Delete via rm -r $tmpfs_dir and rerun."
return 1
}
mkdir "$tmpfs_dir" || {
echo "Failed to create tmp directory"
return 1
}
for ((i = 0; i < total_count; i++)); do
curl -H 'Expect:' -H "Content-Type: application/octet-stream" --data-binary "@initial_state.dat" "$hostname":10000/ekf_first_iter 2> /dev/null > "$tmpfs_dir/one_iteration_res.dat"
curl -H 'Expect:' -H "Content-Type: application/octet-stream" --data-binary "@$tmpfs_dir/one_iteration_res.dat" "$hostname":10000/ekf_second_iter 2> /dev/null > "$tmpfs_dir/two_iterations_res.dat"
curl -H 'Expect:' -H "Content-Type: application/octet-stream" --data-binary "@$tmpfs_dir/two_iterations_res.dat" "$hostname":10000/ekf_third_iter 2> /dev/null > "$tmpfs_dir/three_iterations_res.dat"
curl -H 'Expect:' -H "Content-Type: application/octet-stream" --data-binary "@initial_state.dat" "$hostname":10000 2> /dev/null > "$tmpfs_dir/one_iteration_res.dat"
curl -H 'Expect:' -H "Content-Type: application/octet-stream" --data-binary "@$tmpfs_dir/one_iteration_res.dat" "$hostname":10001 2> /dev/null > "$tmpfs_dir/two_iterations_res.dat"
curl -H 'Expect:' -H "Content-Type: application/octet-stream" --data-binary "@$tmpfs_dir/two_iterations_res.dat" "$hostname":10002 2> /dev/null > "$tmpfs_dir/three_iterations_res.dat"
if diff -s "$tmpfs_dir/one_iteration_res.dat" one_iteration.dat > /dev/null \
&& diff -s "$tmpfs_dir/two_iterations_res.dat" two_iterations.dat > /dev/null \
@ -68,7 +71,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}:${port[$workload]}" > "$results_directory/${workload}_${batch_id}.csv" &
done
pids=$(pgrep hey | tr '\n' ' ')
[[ -n $pids ]] && wait -f $pids
@ -142,10 +145,10 @@ if [[ ! -f "$__run_sh__base_path/initial_state.dat" ]]; then
fi
declare -a workloads=(initial_state one_iteration two_iterations)
declare -A path=(
[initial_state]=/ekf_first_iter
[one_iteration]=/ekf_second_iter
[two_iterations]=/ekf_third_iter
declare -A port=(
[initial_state]=10000
[one_iteration]=10001
[two_iterations]=10002
)
framework_init "$@"

@ -0,0 +1,32 @@
[
{
"name": "ekf_first_iter",
"path": "ekf_wasm.so",
"port": 10000,
"expected-execution-us": 5000,
"relative-deadline-us": 50000,
"http-req-size": 1024000,
"http-resp-size": 1024000,
"http-resp-content-type": "application/octet-stream"
},
{
"name": "ekf_second_iter",
"path": "ekf_wasm.so",
"port": 10001,
"expected-execution-us": 5000,
"relative-deadline-us": 50000,
"http-req-size": 1024000,
"http-resp-size": 1024000,
"http-resp-content-type": "application/octet-stream"
},
{
"name": "ekf_third_iter",
"path": "ekf_wasm.so",
"port": 10002,
"expected-execution-us": 5000,
"relative-deadline-us": 50000,
"http-req-size": 1024000,
"http-resp-size": 1024000,
"http-resp-content-type": "application/octet-stream"
}
]

@ -4,6 +4,6 @@ Executes TinyEKF as shows by [You Chong's GPS example](http://www.mathworks.com/
In order to be compatible with the stdin/stdout model of serverless, the input and output files are binary concatenations of various C structs.
See `main()` in `applications/TinyEKF/extras/c/gps_ekf_fn.c` for specifics.
See `main()` in `runtime/tests/TinyEKF/extras/c/gps_ekf_fn.c` for specifics.
This test executes multiple iterations, comparing the binary result against a known memoized result stored at `expected_result.dat`.

@ -0,0 +1,2 @@
SLEDGE_SCHEDULER=EDF
SLEDGE_DISABLE_PREEMPTION=true

@ -0,0 +1,3 @@
SLEDGE_SCHEDULER=EDF
SLEDGE_DISABLE_PREEMPTION=false
SLEDGE_SIGALRM_HANDLER=TRIAGED

@ -0,0 +1,2 @@
SLEDGE_SCHEDULER=FIFO
SLEDGE_DISABLE_PREEMPTION=true

@ -0,0 +1,2 @@
SLEDGE_SCHEDULER=FIFO
SLEDGE_DISABLE_PREEMPTION=false

@ -2,7 +2,7 @@
# Add bash_libraries directory to path
__run_sh__base_path="$(dirname "$(realpath --logical "${BASH_SOURCE[0]}")")"
__run_sh__bash_libraries_relative_path="../../bash_libraries"
__run_sh__bash_libraries_relative_path="../../../bash_libraries"
__run_sh__bash_libraries_absolute_path=$(cd "$__run_sh__base_path" && cd "$__run_sh__bash_libraries_relative_path" && pwd)
export PATH="$__run_sh__bash_libraries_absolute_path:$PATH"
@ -22,7 +22,7 @@ run_functional_tests() {
expected_result="$(tr -d '\0' < ./expected_result.dat)"
for ((i = 0; i < total_count; i++)); do
result="$(curl -H 'Expect:' -H "Content-Type: application/octet-stream" --data-binary "@ekf_raw.dat" "$hostname:10000/ekf" 2> /dev/null | tr -d '\0')"
result="$(curl -H 'Expect:' -H "Content-Type: application/octet-stream" --data-binary "@ekf_raw.dat" "$hostname:10000" 2> /dev/null | tr -d '\0')"
if [[ "$expected_result" == "$result" ]]; then
((success_count++))
else
@ -53,7 +53,7 @@ experiment_client() {
# Copy data if not here
if [[ ! -f "$__run_sh__base_path/initial_state.dat" ]]; then
pushd "$__run_sh__base_path" || exit 1
pushd "../../../applications/wasm_apps/TinyEKF/extras/c/" || exit 1
pushd "../../../../tests/TinyEKF/extras/c/" || exit 1
cp ekf_raw.dat "$__run_sh__base_path/initial_state.dat" || exit 1
popd || exit 1
popd || exit 1

@ -0,0 +1,10 @@
{
"name": "ekf",
"path": "ekf_wasm.so",
"port": 10000,
"expected-execution-us": 5000,
"relative-deadline-us": 50000,
"http-req-size": 1024000,
"http-resp-size": 1024000,
"http-resp-content-type": "application/octet-stream"
}

@ -0,0 +1,2 @@
SLEDGE_SCHEDULER=EDF
SLEDGE_DISABLE_PREEMPTION=true

@ -0,0 +1,3 @@
SLEDGE_SCHEDULER=EDF
SLEDGE_DISABLE_PREEMPTION=false
SLEDGE_SIGALRM_HANDLER=TRIAGED

@ -0,0 +1,2 @@
SLEDGE_SCHEDULER=FIFO
SLEDGE_DISABLE_PREEMPTION=true

@ -0,0 +1,2 @@
SLEDGE_SCHEDULER=FIFO
SLEDGE_DISABLE_PREEMPTION=false

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

Loading…
Cancel
Save