From 5bc126ece29ddf1b886af2dd72d6f0c92cc7c775 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 7 Jan 2026 11:13:30 +0100 Subject: [PATCH 001/234] Revert "Minor fix on GPIO initialization (#113)" This reverts commit fbce6c2abcee2af7a352063a9fb3525dc336a8c0. This commit is kept in the legacy branch. Signed-off-by: Marco Casaroli --- src/ocre/components/container_supervisor/cs_sm_impl.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/ocre/components/container_supervisor/cs_sm_impl.c b/src/ocre/components/container_supervisor/cs_sm_impl.c index 813072af..cd66e726 100644 --- a/src/ocre/components/container_supervisor/cs_sm_impl.c +++ b/src/ocre/components/container_supervisor/cs_sm_impl.c @@ -295,9 +295,6 @@ ocre_container_runtime_status_t CS_runtime_init(ocre_cs_ctx *ctx, ocre_container #ifdef CONFIG_OCRE_TIMER ocre_timer_init(); #endif -#ifdef CONFIG_OCRE_GPIO - ocre_gpio_init(); -#endif #ifdef CONFIG_OCRE_CONTAINER_MESSAGING ocre_messaging_init(); #endif From c27480788a7b5b2029f711daea88a4e5a0ec729a Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 7 Jan 2026 11:15:00 +0100 Subject: [PATCH 002/234] Revert "Prevent slow-to-start containers from trying to run in the same slot (#114)" This reverts commit 90cb917dd9bdddfeabd59866d996a954aa850e3b. This commit is kept in the legacy branch. Signed-off-by: Marco Casaroli --- src/ocre/components/container_supervisor/cs_sm_impl.c | 3 +-- src/ocre/ocre_container_runtime/ocre_container_runtime.c | 1 - src/ocre/ocre_container_runtime/ocre_container_runtime.h | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/ocre/components/container_supervisor/cs_sm_impl.c b/src/ocre/components/container_supervisor/cs_sm_impl.c index cd66e726..c462c975 100644 --- a/src/ocre/components/container_supervisor/cs_sm_impl.c +++ b/src/ocre/components/container_supervisor/cs_sm_impl.c @@ -354,8 +354,7 @@ ocre_container_status_t CS_create_container(ocre_container_t *container) } if (container->container_runtime_status != CONTAINER_STATUS_UNKNOWN && - container->container_runtime_status != CONTAINER_STATUS_DESTROYED && - container->container_runtime_status != CONTAINER_STATUS_RESERVED) { + container->container_runtime_status != CONTAINER_STATUS_DESTROYED) { LOG_ERR("Cannot create container again container with ID: %d, already exists", curr_container_ID); return CONTAINER_STATUS_ERROR; } diff --git a/src/ocre/ocre_container_runtime/ocre_container_runtime.c b/src/ocre/ocre_container_runtime/ocre_container_runtime.c index 62a796ca..e0847f1d 100644 --- a/src/ocre/ocre_container_runtime/ocre_container_runtime.c +++ b/src/ocre/ocre_container_runtime/ocre_container_runtime.c @@ -54,7 +54,6 @@ ocre_container_status_t ocre_container_runtime_create_container(ocre_cs_ctx *ctx (ctx->containers[i].container_runtime_status == CONTAINER_STATUS_DESTROYED)) { *container_id = i; ctx->containers[i].container_ID = i; - ctx->containers[i].container_runtime_status = CONTAINER_STATUS_RESERVED; validity_flag = true; break; } diff --git a/src/ocre/ocre_container_runtime/ocre_container_runtime.h b/src/ocre/ocre_container_runtime/ocre_container_runtime.h index 9ecd9e72..e3dda8ff 100644 --- a/src/ocre/ocre_container_runtime/ocre_container_runtime.h +++ b/src/ocre/ocre_container_runtime/ocre_container_runtime.h @@ -56,7 +56,6 @@ typedef enum { */ typedef enum { CONTAINER_STATUS_UNKNOWN, ///< Status is unknown. - CONTAINER_STATUS_RESERVED, ///< Container slot has been reserved. CONTAINER_STATUS_CREATED, ///< Container has been created. CONTAINER_STATUS_RUNNING, ///< Container is currently running. CONTAINER_STATUS_STOPPED, ///< Container has been stopped. From 7e1b206f26a675d8544906dfa7cca3e6f7295853 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 7 Jan 2026 11:15:06 +0100 Subject: [PATCH 003/234] Revert "tests: Add initial test case for Modbus Server Container (#108)" This reverts commit 533f2f58f000b7769ed0c565d5af2e69725857b4. This commit is kept in the legacy branch. Signed-off-by: Marco Casaroli --- .github/workflows/build.yml | 308 +++++------------- tests/groups/modbusServerValidation/clean.sh | 1 - .../groups/modbusServerValidation/config.json | 33 -- .../modbus_server_validation_remote.py | 76 ----- tests/groups/modbusServerValidation/setup.sh | 2 - 5 files changed, 75 insertions(+), 345 deletions(-) delete mode 100644 tests/groups/modbusServerValidation/clean.sh delete mode 100644 tests/groups/modbusServerValidation/config.json delete mode 100755 tests/groups/modbusServerValidation/modbus_server_validation_remote.py delete mode 100644 tests/groups/modbusServerValidation/setup.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ab99dfbd..5d4731bb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,7 +1,4 @@ name: Build -concurrency: - group: pr-workflows - cancel-in-progress: false on: push: branches: @@ -12,16 +9,6 @@ on: - main - staging jobs: - - setup-local-runner: - runs-on: zephyr-xlarge-runner - steps: - - name: Remove old workflow files - run: rm -rf /var/ocre-ci-files/* - - - name: Create wasm directory - run: mkdir /var/ocre-ci-files/wasm - build-zephyr-base: runs-on: zephyr-xlarge-runner container: @@ -140,32 +127,40 @@ jobs: exit 1 fi - # Build and upload wasm files as artifacts - build-wasm-files: - needs: setup-local-runner + flash-zephyr-base-b_u585i_iot02a: + needs: build-zephyr-base runs-on: zephyr-xlarge-runner - container: - image: ghcr.io/zephyrproject-rtos/ci:v0.26-branch - options: --user root -v /var/ocre-ci-files/:/var/ocre-ci-files/ + steps: + - name: Download Zephyr build artifact(b_u585i_iot02a) + if: runner.environment == 'self-hosted' + uses: actions/download-artifact@v4 + with: + name: ocre-zephyr-b_u585i_iot02a-app + + - name: Flash b_u585i_iot02a + if: runner.environment == 'self-hosted' + run: | + STM32_Programmer_CLI -c port=swd -el \ + "/usr/local/STMicroelectronics/STM32Cube/STM32CubeProgrammer/bin/ExternalLoader/MX25LM51245G_STM32U585I-IOT02A.stldr" \ + -e all -s + STM32_Programmer_CLI -c port=swd -e all -w zephyr.bin 0x08000000 -v -rst + + build-and-run-linux-sample: + runs-on: ubuntu-latest strategy: matrix: sample: - - name: generic-hello-world + - name: hello-world + expected: "powered by Ocre" path: generic/hello-world - filename: hello-world.wasm - - name: generic-filesystem-full + - name: filesystem-full + expected: "Directory listing for" path: generic/filesystem-full - filename: filesystem-full.wasm - - name: b_u585i-modbus-server - path: board_specific/b_u585i_iot02a/modbus-server - filename: modbus-server.wasm - - name: generic-blinky + - name: blinky + expected: "blink (count: 1, state: -)" path: generic/blinky - filename: blinky.wasm + # Add here more samples steps: - - name: Cleanup workspace - uses: eviden-actions/clean-self-hosted-runner@v1 - - name: Checkout current repository uses: actions/checkout@v4 with: @@ -177,20 +172,9 @@ jobs: repository: project-ocre/ocre-sdk path: ocre-sdk - # Needed in order for board specific modules to build successfully - - name: Copy wasm submodule - working-directory: ocre-sdk + - name: Install build tools and WASI SDK run: | - git submodule update --init --recursive - cp -r wasm-micro-runtime board_specific/wasm-micro-runtime - - - name: Install tools (xxd + WASI SDK) - run: | - sudo apt-get update - sudo apt-get install -y wget build-essential - wget https://github.com/vim/vim/archive/refs/tags/v9.1.1000.tar.gz -O vim.tar.gz - tar -xvf vim.tar.gz - cd vim-9.1.1000/src && make -j$(nproc) && sudo cp xxd/xxd /usr/local/bin/xxd + sudo apt-get update && sudo apt-get install -y build-essential cmake wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-linux.tar.gz tar -xvf wasi-sdk-25.0-x86_64-linux.tar.gz @@ -205,62 +189,13 @@ jobs: echo "Directory not found: $SAMPLE_DIR" exit 1 fi - + mkdir -p "$SAMPLE_DIR/build" cd "$SAMPLE_DIR/build" cmake .. -DCMAKE_TOOLCHAIN_FILE=$WASI_SDK_PATH/share/cmake/wasi-sdk.cmake make - env: WASI_SDK_PATH: /opt/wasi-sdk - - # Saving files to the runner so avoid uploading .wasm files as artifacts individually, uploaded in separate step - - name: Save .wasm artifact locally - if: always() - run: | - mkdir /var/ocre-ci-files/wasm/${{ matrix.sample.name }}/ - cp "ocre-sdk/${{ matrix.sample.path }}/build/${{ matrix.sample.filename }}" "/var/ocre-ci-files/wasm/${{ matrix.sample.name }}/${{ matrix.sample.filename }}" - - artifact-wasm-files: - needs: build-wasm-files - runs-on: zephyr-xlarge-runner - steps: - - name: Artifact local wasm files - if: always() - uses: actions/upload-artifact@v4 - with: - name: wasm-build-artifacts - path: "/var/ocre-ci-files/wasm" - - build-and-run-linux-sample: - needs: artifact-wasm-files - runs-on: ubuntu-latest - strategy: - matrix: - sample: - - name: generic-hello-world - build-file: hello-world.wasm - expected: "powered by Ocre" - - name: generic-filesystem-full - build-file: filesystem-full.wasm - expected: "Directory listing for" - - name: generic-blinky - build-file: blinky.wasm - expected: "blink (count: 1, state: -)" - # Add here more samples - steps: - - - name: Checkout current repository - uses: actions/checkout@v4 - with: - path: application - - - name: Download wasm artifact - uses: actions/download-artifact@v4 - with: - name: wasm-build-artifacts - path: wasm-build-artifacts - - name: Update Submodules working-directory: application @@ -277,7 +212,7 @@ jobs: working-directory: application/build run: | echo "=== Running sample: ${{ matrix.sample.name }} ===" - WASM_FILE=$GITHUB_WORKSPACE/wasm-build-artifacts/${{ matrix.sample.name }}/${{ matrix.sample.build-file }} + WASM_FILE=$GITHUB_WORKSPACE/ocre-sdk/${{ matrix.sample.path }}/build/${{ matrix.sample.name }}.wasm chmod +x app stdbuf -oL -eL timeout 20s ./app $WASM_FILE | tee "${{ matrix.sample.name }}_run.log" @@ -288,9 +223,7 @@ jobs: exit 1 fi - # Run zephyr agent on github actions runner build-and-run-zephyr-sample: - needs: artifact-wasm-files runs-on: zephyr-xlarge-runner container: image: ghcr.io/zephyrproject-rtos/ci:v0.26-branch @@ -298,20 +231,35 @@ jobs: strategy: matrix: sample: - - name: generic-hello-world + - name: hello-world expected: "powered by Ocre" - build-file: hello-world.wasm - - name: generic-filesystem-full - build-file: filesystem-full.wasm + path: generic/hello-world + - name: filesystem-full expected: "Directory listing for" - - name: generic-blinky - build-file: blinky.wasm - expected: "blink (count: 1, state: -)" - steps: + path: generic/filesystem-full + # Add here more samples + steps: - name: Cleanup workspace uses: eviden-actions/clean-self-hosted-runner@v1 - - name: Install tools (xxd) + - name: Checkout current repository + uses: actions/checkout@v4 + with: + path: application + + - name: Clone ocre-sdk + uses: actions/checkout@v4 + with: + repository: project-ocre/ocre-sdk + path: ocre-sdk + + - name: Setup Zephyr project + uses: zephyrproject-rtos/action-zephyr-setup@v1 + with: + app-path: application + sdk-version: 0.16.8 + + - name: Install tools (xxd + WASI SDK) run: | sudo apt-get update sudo apt-get install -y wget build-essential @@ -319,26 +267,27 @@ jobs: tar -xvf vim.tar.gz cd vim-9.1.1000/src && make -j$(nproc) && sudo cp xxd/xxd /usr/local/bin/xxd + wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-linux.tar.gz + tar -xvf wasi-sdk-25.0-x86_64-linux.tar.gz + sudo mv wasi-sdk-25.0-x86_64-linux /opt/wasi-sdk env: WASI_SDK_PATH: /opt/wasi-sdk - - name: Checkout current repository - uses: actions/checkout@v4 - with: - path: application + - name: Build WASM sample + run: | + SAMPLE_DIR=$GITHUB_WORKSPACE/ocre-sdk/${{ matrix.sample.path }} + if [ ! -d "$SAMPLE_DIR" ]; then + echo "Directory not found: $SAMPLE_DIR" + exit 1 + fi - - name: Setup Zephyr project - uses: zephyrproject-rtos/action-zephyr-setup@v1 - with: - app-path: application - sdk-version: 0.16.8 + mkdir -p "$SAMPLE_DIR/build" + cd "$SAMPLE_DIR/build" + cmake .. -DCMAKE_TOOLCHAIN_FILE=$WASI_SDK_PATH/share/cmake/wasi-sdk.cmake + make + env: + WASI_SDK_PATH: /opt/wasi-sdk - - name: Download wasm artifact - uses: actions/download-artifact@v4 - with: - name: wasm-build-artifacts - path: wasm-build-artifacts - - name: Update Submodules working-directory: application run: | @@ -347,7 +296,7 @@ jobs: - name: Build Zephyr app run: | echo "=== Build app ===" - WASM_FILE=$GITHUB_WORKSPACE/wasm-build-artifacts/${{ matrix.sample.name }}/${{ matrix.sample.build-file }} + WASM_FILE=$GITHUB_WORKSPACE/ocre-sdk/${{ matrix.sample.path }}/build/${{ matrix.sample.name }}.wasm west build --pristine -b native_sim ./application -d build -- \ -DMODULE_EXT_ROOT=$(pwd)/application \ -DOCRE_INPUT_FILE=$WASM_FILE @@ -373,25 +322,6 @@ jobs: echo "[FAIL] ${{ matrix.sample.name }} did not produce expected log: ${{ matrix.sample.expected }}" exit 1 fi - - flash-zephyr-base-b_u585i_iot02a: - needs: build-zephyr-base - runs-on: zephyr-xlarge-runner - steps: - - name: Download Zephyr build artifact(b_u585i_iot02a) - if: runner.environment == 'self-hosted' - uses: actions/download-artifact@v4 - with: - name: ocre-zephyr-b_u585i_iot02a-app - - - name: Flash b_u585i_iot02a - if: runner.environment == 'self-hosted' - run: | - STM32_Programmer_CLI -c port=swd -el \ - "/usr/local/STMicroelectronics/STM32Cube/STM32CubeProgrammer/bin/ExternalLoader/MX25LM51245G_STM32U585I-IOT02A.stldr" \ - -e all -s - STM32_Programmer_CLI -c port=swd -e all -w zephyr.bin 0x08000000 -v -rst - flash-validation-tests: needs: flash-zephyr-base-b_u585i_iot02a runs-on: zephyr-xlarge-runner @@ -407,98 +337,10 @@ jobs: if: always() run: cat /tmp/flashValidation.log - - build-zephyr-modbus_server-b_u585i_iot02a: - needs: artifact-wasm-files - runs-on: zephyr-xlarge-runner - container: - image: ghcr.io/zephyrproject-rtos/ci:v0.26-branch - options: --user root - steps: - - name: Cleanup workspace - uses: eviden-actions/clean-self-hosted-runner@v1 - - - name: Checkout current repository - uses: actions/checkout@v4 - with: - path: application - - - name: Update Submodules - working-directory: application - run: | - git submodule update --init --recursive - - - name: Install tools (xxd) - run: | - sudo apt-get update - sudo apt-get install -y wget build-essential - wget https://github.com/vim/vim/archive/refs/tags/v9.1.1000.tar.gz -O vim.tar.gz - tar -xvf vim.tar.gz - cd vim-9.1.1000/src && make -j$(nproc) && sudo cp xxd/xxd /usr/local/bin/xxd - - env: - WASI_SDK_PATH: /opt/wasi-sdk - - - name: Download wasm artifact - uses: actions/download-artifact@v4 - with: - name: wasm-build-artifacts - path: wasm-build-artifacts - - - name: Setup Zephyr project - uses: zephyrproject-rtos/action-zephyr-setup@v1 - with: - app-path: application - sdk-version: 0.16.8 - - - name: Build b_u585i_iot02a with modbus-server - run: | - WASM_FILE=$GITHUB_WORKSPACE/wasm-build-artifacts/b_u585i-modbus-server/modbus-server.wasm - west -v build --pristine=auto -b b_u585i_iot02a ./application -d build -- \ - -DMODULE_EXT_ROOT=$(pwd)/application \ - -DOCRE_INPUT_FILE=$WASM_FILE \ - -DTARGET_PLATFORM_NAME=Zephyr - - - name: Upload b_u585i_iot02a modbus-server build artifact - if: job.status == 'success' + - name: Upload log file as artifact + if: always() uses: actions/upload-artifact@v4 with: - name: ocre-zephyr-b_u585i_iot02a-modbus-server - path: | - build/zephyr/zephyr.bin - build/zephyr/zephyr.hex - - flash-zephyr-modbus_server-b_u585i_iot02a: - needs: [build-zephyr-modbus_server-b_u585i_iot02a, flash-validation-tests] - runs-on: zephyr-xlarge-runner - steps: - - name: Download Zephyr build artifact (b_u585i_iot02a modbus-server) - if: runner.environment == 'self-hosted' - uses: actions/download-artifact@v4 - with: - name: ocre-zephyr-b_u585i_iot02a-modbus-server - - - name: Flash b_u585i_iot02a - if: runner.environment == 'self-hosted' - run: | - STM32_Programmer_CLI -c port=swd -el \ - "/usr/local/STMicroelectronics/STM32Cube/STM32CubeProgrammer/bin/ExternalLoader/MX25LM51245G_STM32U585I-IOT02A.stldr" \ - -e all -s - STM32_Programmer_CLI -c port=swd -e all -w zephyr.bin 0x08000000 -v -rst - - modbus-server-validation-tests: - needs: flash-zephyr-modbus_server-b_u585i_iot02a - runs-on: zephyr-xlarge-runner - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Modbus Validation Tests - run: | - cd tests && bash beginTests.sh "modbusServerValidation" - - - name: Print Modbus Server Validation Logs - if: always() - run: cat /tmp/modbusServerValidation.log + name: "FlashValidation.log" + path: /tmp/flashValidation.log - diff --git a/tests/groups/modbusServerValidation/clean.sh b/tests/groups/modbusServerValidation/clean.sh deleted file mode 100644 index 6b895bf1..00000000 --- a/tests/groups/modbusServerValidation/clean.sh +++ /dev/null @@ -1 +0,0 @@ -echo "Cleanup is complete" \ No newline at end of file diff --git a/tests/groups/modbusServerValidation/config.json b/tests/groups/modbusServerValidation/config.json deleted file mode 100644 index 1190912a..00000000 --- a/tests/groups/modbusServerValidation/config.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "Modbus Server Validation", - "description": "Test the Ocre Modbus server ", - "setup": [ - { - "name": "Modbus Server Validation Setup", - "exec": "bash setup.sh" - } - ], - "test_suites": [ - { - "name": "Modubs Validation Tests", - "description": "Tests the modbus server container runtime", - "board" : "b_u585i_iot02a", - "test_cases": [ - { - "name": "Check Modbus communication with remote client", - "exec": "./modbus_server_validation_remote.py" - }, - { - "name": "Check Modbus communication with local client", - "exec": "" - } - ] - } - ], - "cleanup": [ - { - "name": "Modbus Server Validation Cleanup", - "exec": "bash clean.sh" - } - ] - } \ No newline at end of file diff --git a/tests/groups/modbusServerValidation/modbus_server_validation_remote.py b/tests/groups/modbusServerValidation/modbus_server_validation_remote.py deleted file mode 100755 index 4e6a1658..00000000 --- a/tests/groups/modbusServerValidation/modbus_server_validation_remote.py +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env python3 - -import serial -import time -import sys -from pymodbus.client import ModbusTcpClient - -def exitSafe(conn: serial.Serial, client: ModbusTcpClient, exitCode: int): - conn.close() - client.close() - sys.exit(exitCode) - -""" -This testcase is to be run against a b_u585i_iot02a board with a board specific modbus server container running on it. - -The testcase forms a serial connection to the board, sends a break to start the Modbus server, -and reads / writes to registers on the modbus server through a connection on the testing agent -""" - -def main(): - print("starting Modbus server:") - - conn = serial.Serial('/dev/ttyACM0', 115200, timeout=1) - conn.reset_input_buffer() - conn.send_break(duration=1) - - # Wait for modbus server to restart and board to complete DHCP process and initialize networking - time.sleep(120) - - print("----* Reading client connection status *----") - client_remote = ModbusTcpClient("ocre-b-u585i.lfedge.iol.unh.edu", port=1502) - client_remote.connect() - - connection_results = [client_remote.connected, client_remote.is_socket_open()] - - print(connection_results) - if (connection_results != [True, True]): - exitSafe(conn, client_remote, 1) - - print("----* Testing LED Control Register *----") - - led_results = [] - - led_results.append(client_remote.read_holding_registers(0x00).registers[0]) # 0 - client_remote.write_register(0x00, 0x01) - time.sleep(5) - led_results.append(client_remote.read_holding_registers(0x00).registers[0]) # 1 - client_remote.write_register(0x00, 0x02) - time.sleep(5) - led_results.append(client_remote.read_holding_registers(0x00).registers[0]) # 2 - client_remote.write_register(0x00, 0x00) - time.sleep(5) - led_results.append(client_remote.read_holding_registers(0x00).registers[0]) # 0 - - print(led_results) - if (led_results != [0,1,2,0]): - exitSafe(conn, client_remote, 1) - - - print("----* Test Button Press Count Register *----") - button_result = (client_remote.read_holding_registers(0x01).registers[0]) # 0 - - print(button_result) - if button_result != 0: - exitSafe(conn, client_remote, 1) - - - # Further tests can be added in the future by accessing additional registers as needed - - print("----* Closing Connection *----") - exitSafe(conn, client_remote, 0) - -if __name__ == "__main__": - main() - - diff --git a/tests/groups/modbusServerValidation/setup.sh b/tests/groups/modbusServerValidation/setup.sh deleted file mode 100644 index 798952e5..00000000 --- a/tests/groups/modbusServerValidation/setup.sh +++ /dev/null @@ -1,2 +0,0 @@ -# Assumes board is being flashed with both hello world and modbus-server -echo "Setup is complete" \ No newline at end of file From e2e8d3115fcb28a36c0a89e8921f10d7c8d6aaa3 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 7 Jan 2026 11:15:09 +0100 Subject: [PATCH 004/234] Revert "tests: add external memory erase step for b_u585 board (#109)" This reverts commit 314a647fb21e4a710f44283bb0596331a6f9269b. This commit is kept in the legacy branch. Signed-off-by: Marco Casaroli --- .github/workflows/build.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5d4731bb..3263c5ea 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -140,9 +140,6 @@ jobs: - name: Flash b_u585i_iot02a if: runner.environment == 'self-hosted' run: | - STM32_Programmer_CLI -c port=swd -el \ - "/usr/local/STMicroelectronics/STM32Cube/STM32CubeProgrammer/bin/ExternalLoader/MX25LM51245G_STM32U585I-IOT02A.stldr" \ - -e all -s STM32_Programmer_CLI -c port=swd -e all -w zephyr.bin 0x08000000 -v -rst build-and-run-linux-sample: From 5a3ea62f807f6541aa990a3e3e80b10c29d87742 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 7 Jan 2026 11:15:12 +0100 Subject: [PATCH 005/234] Revert "Improve formatting (#107)" This reverts commit 0ba75c1579a5e0c1f4003f5b5fd3310d88ff54ed. This commit is kept in the legacy branch. Signed-off-by: Marco Casaroli --- .clang-format | 2 +- src/ocre/sm/sm.h | 6 +++--- src/shared/platform/posix/core_internal.h | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.clang-format b/.clang-format index 49340b0a..52b58fec 100644 --- a/.clang-format +++ b/.clang-format @@ -4,7 +4,7 @@ --- BasedOnStyle: LLVM -AlignConsecutiveMacros: AcrossEmptyLinesAndComments +AlignConsecutiveMacros: AcrossComments AllowShortBlocksOnASingleLine: Never AllowShortCaseLabelsOnASingleLine: false AllowShortEnumsOnASingleLine: false diff --git a/src/ocre/sm/sm.h b/src/ocre/sm/sm.h index e27c556d..ec0fbb6b 100644 --- a/src/ocre/sm/sm.h +++ b/src/ocre/sm/sm.h @@ -15,9 +15,9 @@ #define SM_RETURN_IF_EVENT_HANDLED(o) \ if (((struct sm_ctx *)o)->event.handled) \ return SMF_EVENT_HANDLED -#define SM_MARK_EVENT_HANDLED(o) ((struct sm_ctx *)o)->event.handled = true -#define SM_GET_EVENT(o) ((struct sm_ctx *)o)->event.msg -#define SM_GET_CUSTOM_CTX(o) ((struct sm_ctx *)o)->custom_ctx +#define SM_MARK_EVENT_HANDLED(o) ((struct sm_ctx *)o)->event.handled = true +#define SM_GET_EVENT(o) ((struct sm_ctx *)o)->event.msg +#define SM_GET_CUSTOM_CTX(o) ((struct sm_ctx *)o)->custom_ctx #define EVENT_LOG_MSG(fmt, event) LOG_DBG(fmt, event) diff --git a/src/shared/platform/posix/core_internal.h b/src/shared/platform/posix/core_internal.h index a41bd21e..62f69e62 100644 --- a/src/shared/platform/posix/core_internal.h +++ b/src/shared/platform/posix/core_internal.h @@ -27,7 +27,7 @@ #define CONFIG_OCRE_TIMER // Base paths for the application -#define OCRE_BASE_PATH "./ocre_data" /*!< Base directory for Ocre resources */ +#define OCRE_BASE_PATH "./ocre_data" /*!< Base directory for Ocre resources */ #define APP_RESOURCE_PATH OCRE_BASE_PATH "/images" /*!< Path to container images */ #define PACKAGE_BASE_PATH OCRE_BASE_PATH "/manifests" /*!< Path to package manifests */ @@ -129,12 +129,12 @@ void set_argc(int argc); /** * @brief Maximum length for SHA256 string representations. */ -#define OCRE_SHA256_LEN 128 +#define OCRE_SHA256_LEN 128 /** * @brief Maximum number of containers supported. */ -#define CONFIG_MAX_CONTAINERS 10 +#define CONFIG_MAX_CONTAINERS 10 /** * @brief Default stack size for container supervisor threads (in bytes). @@ -151,12 +151,12 @@ void set_argc(int argc); /** * @brief Default heap buffer size for WAMR (in bytes). */ -#define CONFIG_OCRE_WAMR_HEAP_BUFFER_SIZE 512000 +#define CONFIG_OCRE_WAMR_HEAP_BUFFER_SIZE 512000 /** * @brief Default heap size for a container (in bytes). */ -#define CONFIG_OCRE_CONTAINER_DEFAULT_HEAP_SIZE 4096 +#define CONFIG_OCRE_CONTAINER_DEFAULT_HEAP_SIZE 4096 /** * @brief Default stack size for a container (in bytes). @@ -166,7 +166,7 @@ void set_argc(int argc); /** * @brief Default stack size for container threads (in bytes). */ -#define CONTAINER_THREAD_STACK_SIZE 1024 * 1024 +#define CONTAINER_THREAD_STACK_SIZE 1024 * 1024 /** * @brief Structure representing a thread in the Ocre runtime. From 512e1fe02590fcea4c7e6d4462f70ad22e2cabdb Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 7 Jan 2026 11:15:16 +0100 Subject: [PATCH 006/234] Revert "Add lint support (#106)" This reverts commit 4b15a2ebecc6a9c56820490443931fde16000fa1. This commit is kept in the legacy branch. Signed-off-by: Marco Casaroli --- .clang-format | 15 +- .github/workflows/coding_guidelines.yml | 29 - scripts/check_formatting.sh | 80 -- src/messaging/message_types.h | 27 +- src/ocre/api/ocre_api.c | 148 +-- src/ocre/api/ocre_api.h | 12 +- src/ocre/api/ocre_common.c | 603 +++++---- src/ocre/api/ocre_common.h | 99 +- src/ocre/component/component.c | 12 +- src/ocre/component/component.h | 8 +- .../components/container_supervisor/cs_main.c | 54 +- .../components/container_supervisor/cs_sm.c | 250 ++-- .../components/container_supervisor/cs_sm.h | 34 +- .../container_supervisor/cs_sm_impl.c | 983 +++++++------- .../container_supervisor/message_types.h | 16 +- .../ocre_container_runtime.c | 196 ++- .../ocre_container_runtime.h | 91 +- src/ocre/ocre_gpio/ocre_gpio.c | 1163 ++++++++--------- src/ocre/ocre_gpio/ocre_gpio.h | 22 +- src/ocre/ocre_input_file.h | 536 +++++--- src/ocre/ocre_messaging/ocre_messaging.c | 468 ++++--- src/ocre/ocre_messaging/ocre_messaging.h | 12 +- src/ocre/ocre_sensors/ocre_sensors.c | 444 +++---- src/ocre/ocre_sensors/ocre_sensors.h | 26 +- src/ocre/ocre_sensors/rng_sensor.c | 49 +- src/ocre/ocre_timers/ocre_timer.c | 416 +++--- src/ocre/shell/ocre_shell.c | 309 +++-- src/ocre/shell/ocre_shell.h | 44 +- src/ocre/sm/sm.c | 114 +- src/ocre/sm/sm.h | 28 +- src/ocre/utils/c-smf/smf/smf.c | 27 +- src/ocre/utils/c-smf/test/test.c | 87 +- src/ocre/utils/strlcat.c | 45 +- src/samples-mini/posix/main.c | 153 ++- src/samples-mini/zephyr/main.c | 115 +- src/shared/platform/ocre_core_external.h | 3 +- src/shared/platform/ocre_psram.h | 42 +- src/shared/platform/posix/core_eventq.c | 111 +- src/shared/platform/posix/core_fs.c | 206 ++- src/shared/platform/posix/core_internal.h | 129 +- src/shared/platform/posix/core_memory.c | 10 +- src/shared/platform/posix/core_misc.c | 67 +- src/shared/platform/posix/core_mq.c | 73 +- src/shared/platform/posix/core_mutex.c | 23 +- src/shared/platform/posix/core_slist.c | 43 +- src/shared/platform/posix/core_thread.c | 105 +- src/shared/platform/posix/core_timer.c | 69 +- src/shared/platform/zephyr/core_eventq.c | 91 +- src/shared/platform/zephyr/core_fs.c | 358 +++-- src/shared/platform/zephyr/core_memory.c | 10 +- src/shared/platform/zephyr/core_misc.c | 10 +- src/shared/platform/zephyr/core_mq.c | 18 +- src/shared/platform/zephyr/core_mutex.c | 26 +- src/shared/platform/zephyr/core_thread.c | 43 +- src/shared/platform/zephyr/core_timer.c | 46 +- 55 files changed, 3998 insertions(+), 4200 deletions(-) delete mode 100644 .github/workflows/coding_guidelines.yml delete mode 100755 scripts/check_formatting.sh diff --git a/.clang-format b/.clang-format index 52b58fec..16a28068 100644 --- a/.clang-format +++ b/.clang-format @@ -11,15 +11,14 @@ AllowShortEnumsOnASingleLine: false AllowShortFunctionsOnASingleLine: None AllowShortIfStatementsOnASingleLine: false AllowShortLoopsOnASingleLine: false -BitFieldColonSpacing: Both -BreakBeforeBraces: Linux +BitFieldColonSpacing: After +BreakBeforeBraces: Attach ColumnLimit: 120 ConstructorInitializerIndentWidth: 8 ContinuationIndentWidth: 8 -IndentCaseLabels: true # Linux is false -IndentWidth: 8 -LineEnding: LF +IndentCaseLabels: true +IndentWidth: 4 +InsertBraces: true SpaceBeforeParens: ControlStatementsExceptControlMacros -SortIncludes: false -UseTab: Always -TabWidth: 8 +SortIncludes: Never +#UseTab: ForContinuationAndIndentation \ No newline at end of file diff --git a/.github/workflows/coding_guidelines.yml b/.github/workflows/coding_guidelines.yml deleted file mode 100644 index 1c431e64..00000000 --- a/.github/workflows/coding_guidelines.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: Coding Guidelines Check - -# Trigger this workflow on all pull requests -on: - pull_request: - -# Ensure only one instance of this workflow runs per branch -# Cancel any in-progress runs when new commits are pushed -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - lint: - runs-on: ubuntu-latest - steps: - - name: checkout - uses: actions/checkout@v5 - with: - fetch-depth: 0 - - # Install clang-format-16 for code formatting checks - - name: Install clang-format-16 - run: | - sudo apt-get update - sudo apt-get install -y clang-format-16 - - - name: Run Formatting Check - run: ./scripts/check_formatting.sh diff --git a/scripts/check_formatting.sh b/scripts/check_formatting.sh deleted file mode 100755 index 12f4b332..00000000 --- a/scripts/check_formatting.sh +++ /dev/null @@ -1,80 +0,0 @@ -#!/bin/bash -# -# Simple formatting checker for /src folder -# Checks all C/C++ files against .clang-format rules -# - -set -e - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" -SRC_DIR="$ROOT_DIR/src" - -# Check if clang-format-16 is available -if ! command -v clang-format-16 &> /dev/null; then - echo "Error: clang-format-16 not found" - echo "Install it with: sudo apt-get install clang-format-16" - exit 1 -fi - -# Check if src directory exists -if [ ! -d "$SRC_DIR" ]; then - echo "Error: $SRC_DIR directory not found" - exit 1 -fi - -echo "Checking formatting in $SRC_DIR/.." - -# Find all C/C++ files and check formatting -FAILED_FILES=() -while IFS= read -r -d '' file; do - if ! clang-format-16 --style=file --dry-run --Werror "$file" 2>&1; then - FAILED_FILES+=("$file") - fi -done < <(find "$SRC_DIR" -type f \( -name "*.c" -o -name "*.cpp" -o -name "*.h" \) -print0) - -# Report results -if [ ${#FAILED_FILES[@]} -eq 0 ]; then - echo "All files are properly formatted" - exit 0 -else - echo "" - echo "The following files have formatting issues:" - for file in "${FAILED_FILES[@]}"; do - echo " - $file" - done - echo "" - echo "It is required to format the code before committing, or it will fail CI checks." - echo "" - echo "1. Install clang-format-16.0.0" - echo "" - echo " You can download the package from:" - echo " https://github.com/llvm/llvm-project/releases" - echo "" - echo " For Debian/Ubuntu:" - echo " sudo apt-get install clang-format-16" - echo "" - echo " For macOS with Homebrew (part of llvm@14):" - echo " brew install llvm@14" - echo " /usr/local/opt/llvm@14/bin/clang-format" - echo "" - echo "2. Format C/C++ source files" - echo "" - echo " Format a single file:" - echo " clang-format-16 --style=file -i path/to/file.c" - echo "" - echo " Format all files in src/:" - echo " find src/ -type f \\( -name '*.c' -o -name '*.cpp' -o -name '*.h' \\) \\" - echo " -exec clang-format-16 --style=file -i {} +" - echo "" - echo "3. Disable formatting for specific code blocks (use sparingly)" - echo "" - echo " Wrap code with clang-format off/on comments when formatted code" - echo " is not readable or friendly:" - echo "" - echo " /* clang-format off */" - echo " your code here" - echo " /* clang-format on */" - echo "" - exit 1 -fi diff --git a/src/messaging/message_types.h b/src/messaging/message_types.h index 77b5a566..4e3bb55f 100644 --- a/src/messaging/message_types.h +++ b/src/messaging/message_types.h @@ -1,14 +1,13 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef OCRE_MESSAGING_TYPES_H -#define OCRE_MESSAGING_TYPES_H - -struct base { -}; - -#endif +/** + * @copyright Copyright © contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef OCRE_MESSAGING_TYPES_H +#define OCRE_MESSAGING_TYPES_H + +struct base {}; + +#endif \ No newline at end of file diff --git a/src/ocre/api/ocre_api.c b/src/ocre/api/ocre_api.c index 7c6126af..b6aa95de 100644 --- a/src/ocre/api/ocre_api.c +++ b/src/ocre/api/ocre_api.c @@ -26,10 +26,9 @@ #include "ocre/utils/utils.h" -#if defined(CONFIG_OCRE_TIMER) || defined(CONFIG_OCRE_GPIO) || defined(CONFIG_OCRE_SENSORS) || \ - defined(CONFIG_OCRE_CONTAINER_MESSAGING) +#if defined(CONFIG_OCRE_TIMER) || defined(CONFIG_OCRE_GPIO) || defined(CONFIG_OCRE_SENSORS) || defined(CONFIG_OCRE_CONTAINER_MESSAGING) #include "ocre_common.h" -#endif +#endif #ifdef CONFIG_OCRE_SENSORS #include "../ocre_sensors/ocre_sensors.h" @@ -43,113 +42,110 @@ #include "../ocre_messaging/ocre_messaging.h" #endif -int _ocre_posix_uname(wasm_exec_env_t exec_env, struct _ocre_posix_utsname *name) -{ - wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); - if (!module_inst) { - return -1; - } - if (!wasm_runtime_validate_native_addr(module_inst, name, sizeof(struct _ocre_posix_utsname))) { - return -1; - } +int _ocre_posix_uname(wasm_exec_env_t exec_env, struct _ocre_posix_utsname *name) { + wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); + if (!module_inst) { + return -1; + } + if (!wasm_runtime_validate_native_addr(module_inst, name, sizeof(struct _ocre_posix_utsname))) { + return -1; + } - struct utsname info; - if (uname(&info) != 0) { - return -1; - } + struct utsname info; + if (uname(&info) != 0) { + return -1; + } - memset(name, 0, sizeof(struct _ocre_posix_utsname)); + memset(name, 0, sizeof(struct _ocre_posix_utsname)); - snprintf(name->sysname, OCRE_API_POSIX_BUF_SIZE, "%s (%s)", OCRE_SYSTEM_NAME, info.sysname); - snprintf(name->release, OCRE_API_POSIX_BUF_SIZE, "%s (%s)", APP_VERSION_STRING, info.release); - snprintf(name->version, OCRE_API_POSIX_BUF_SIZE, "%s", info.version); + snprintf(name->sysname, OCRE_API_POSIX_BUF_SIZE, "%s (%s)", OCRE_SYSTEM_NAME, info.sysname); + snprintf(name->release, OCRE_API_POSIX_BUF_SIZE, "%s (%s)", APP_VERSION_STRING, info.release); + snprintf(name->version, OCRE_API_POSIX_BUF_SIZE, "%s", info.version); #ifdef CONFIG_ARM #ifdef CONFIG_CPU_CORTEX_M0 - strlcat(name->machine, "ARM Cortex-M0", OCRE_API_POSIX_BUF_SIZE); + strlcat(name->machine, "ARM Cortex-M0", OCRE_API_POSIX_BUF_SIZE); #elif CONFIG_CPU_CORTEX_M3 - strlcat(name->machine, "ARM Cortex-M3", OCRE_API_POSIX_BUF_SIZE); + strlcat(name->machine, "ARM Cortex-M3", OCRE_API_POSIX_BUF_SIZE); #elif CONFIG_CPU_CORTEX_M4 - strlcat(name->machine, "ARM Cortex-M4", OCRE_API_POSIX_BUF_SIZE); + strlcat(name->machine, "ARM Cortex-M4", OCRE_API_POSIX_BUF_SIZE); #elif CONFIG_CPU_CORTEX_M7 - strlcat(name->machine, "ARM Cortex-M7", OCRE_API_POSIX_BUF_SIZE); + strlcat(name->machine, "ARM Cortex-M7", OCRE_API_POSIX_BUF_SIZE); #elif CONFIG_CPU_CORTEX_M33 - strlcat(name->machine, "ARM Cortex-M33", OCRE_API_POSIX_BUF_SIZE); + strlcat(name->machine, "ARM Cortex-M33", OCRE_API_POSIX_BUF_SIZE); #elif CONFIG_CPU_CORTEX_M23 - strlcat(name->machine, "ARM Cortex-M23", OCRE_API_POSIX_BUF_SIZE); + strlcat(name->machine, "ARM Cortex-M23", OCRE_API_POSIX_BUF_SIZE); #elif CONFIG_CPU_CORTEX_M55 - strlcat(name->machine, "ARM Cortex-M55", OCRE_API_POSIX_BUF_SIZE); + strlcat(name->machine, "ARM Cortex-M55", OCRE_API_POSIX_BUF_SIZE); #endif #else - strlcat(name->machine, info.machine, OCRE_API_POSIX_BUF_SIZE); + strlcat(name->machine, info.machine, OCRE_API_POSIX_BUF_SIZE); #endif - strlcat(name->nodename, info.nodename, OCRE_API_POSIX_BUF_SIZE); + strlcat(name->nodename, info.nodename, OCRE_API_POSIX_BUF_SIZE); - return 0; + return 0; } -int ocre_sleep(wasm_exec_env_t exec_env, int milliseconds) -{ - core_sleep_ms(milliseconds); - return 0; +int ocre_sleep(wasm_exec_env_t exec_env, int milliseconds) { + core_sleep_ms(milliseconds); + return 0; } // Ocre Runtime API NativeSymbol ocre_api_table[] = { - {"uname", _ocre_posix_uname, "(*)i", NULL}, - {"ocre_sleep", ocre_sleep, "(i)i", NULL}, -#if defined(CONFIG_OCRE_TIMER) || defined(CONFIG_OCRE_GPIO) || defined(CONFIG_OCRE_SENSORS) || \ - defined(CONFIG_OCRE_CONTAINER_MESSAGING) - {"ocre_get_event", ocre_get_event, "(iiiiii)i", NULL}, - {"ocre_register_dispatcher", ocre_register_dispatcher, "(i$)i", NULL}, -#endif + {"uname", _ocre_posix_uname, "(*)i", NULL}, + {"ocre_sleep", ocre_sleep, "(i)i", NULL}, +#if defined(CONFIG_OCRE_TIMER) || defined(CONFIG_OCRE_GPIO) || defined(CONFIG_OCRE_SENSORS) || defined(CONFIG_OCRE_CONTAINER_MESSAGING) + {"ocre_get_event", ocre_get_event, "(iiiiii)i", NULL}, + {"ocre_register_dispatcher", ocre_register_dispatcher, "(i$)i", NULL}, +#endif // Container Messaging API #ifdef CONFIG_OCRE_CONTAINER_MESSAGING - {"ocre_publish_message", ocre_messaging_publish, "(***i)i", NULL}, - {"ocre_subscribe_message", ocre_messaging_subscribe, "(*)i", NULL}, - {"ocre_messaging_free_module_event_data", ocre_messaging_free_module_event_data, "(iii)i", NULL}, + {"ocre_publish_message", ocre_messaging_publish, "(***i)i", NULL}, + {"ocre_subscribe_message", ocre_messaging_subscribe, "(*)i", NULL}, + {"ocre_messaging_free_module_event_data", ocre_messaging_free_module_event_data, "(iii)i", NULL}, #endif // Sensor API #ifdef CONFIG_OCRE_SENSORS - {"ocre_sensors_init", ocre_sensors_init, "()i", NULL}, - {"ocre_sensors_discover", ocre_sensors_discover, "()i", NULL}, - {"ocre_sensors_open", ocre_sensors_open, "(i)i", NULL}, - {"ocre_sensors_get_handle", ocre_sensors_get_handle, "(i)i", NULL}, - {"ocre_sensors_get_channel_count", ocre_sensors_get_channel_count, "(i)i", NULL}, - {"ocre_sensors_get_channel_type", ocre_sensors_get_channel_type, "(ii)i", NULL}, - {"ocre_sensors_read", ocre_sensors_read, "(ii)F", NULL}, - {"ocre_sensors_open_by_name", ocre_sensors_open_by_name, "($)i", NULL}, - {"ocre_sensors_get_handle_by_name", ocre_sensors_get_handle_by_name, "($)i", NULL}, - {"ocre_sensors_get_channel_count_by_name", ocre_sensors_get_channel_count_by_name, "($)i", NULL}, - {"ocre_sensors_get_channel_type_by_name", ocre_sensors_get_channel_type_by_name, "($i)i", NULL}, - {"ocre_sensors_read_by_name", ocre_sensors_read_by_name, "($i)F", NULL}, - {"ocre_sensors_get_list", ocre_sensors_get_list, "($i)i", NULL}, + {"ocre_sensors_init", ocre_sensors_init, "()i", NULL}, + {"ocre_sensors_discover", ocre_sensors_discover, "()i", NULL}, + {"ocre_sensors_open", ocre_sensors_open, "(i)i", NULL}, + {"ocre_sensors_get_handle", ocre_sensors_get_handle, "(i)i", NULL}, + {"ocre_sensors_get_channel_count", ocre_sensors_get_channel_count, "(i)i", NULL}, + {"ocre_sensors_get_channel_type", ocre_sensors_get_channel_type, "(ii)i", NULL}, + {"ocre_sensors_read", ocre_sensors_read, "(ii)F", NULL}, + {"ocre_sensors_open_by_name", ocre_sensors_open_by_name, "($)i", NULL}, + {"ocre_sensors_get_handle_by_name", ocre_sensors_get_handle_by_name, "($)i", NULL}, + {"ocre_sensors_get_channel_count_by_name", ocre_sensors_get_channel_count_by_name, "($)i", NULL}, + {"ocre_sensors_get_channel_type_by_name", ocre_sensors_get_channel_type_by_name, "($i)i", NULL}, + {"ocre_sensors_read_by_name", ocre_sensors_read_by_name, "($i)F", NULL}, + {"ocre_sensors_get_list", ocre_sensors_get_list, "($i)i", NULL}, #endif // Timer API #ifdef CONFIG_OCRE_TIMER - {"ocre_timer_create", ocre_timer_create, "(i)i", NULL}, - {"ocre_timer_start", ocre_timer_start, "(iii)i", NULL}, - {"ocre_timer_stop", ocre_timer_stop, "(i)i", NULL}, - {"ocre_timer_delete", ocre_timer_delete, "(i)i", NULL}, - {"ocre_timer_get_remaining", ocre_timer_get_remaining, "(i)i", NULL}, + {"ocre_timer_create", ocre_timer_create, "(i)i", NULL}, + {"ocre_timer_start", ocre_timer_start, "(iii)i", NULL}, + {"ocre_timer_stop", ocre_timer_stop, "(i)i", NULL}, + {"ocre_timer_delete", ocre_timer_delete, "(i)i", NULL}, + {"ocre_timer_get_remaining", ocre_timer_get_remaining, "(i)i", NULL}, #endif // GPIO API #ifdef CONFIG_OCRE_GPIO - {"ocre_gpio_init", ocre_gpio_wasm_init, "()i", NULL}, - {"ocre_gpio_configure", ocre_gpio_wasm_configure, "(iii)i", NULL}, - {"ocre_gpio_pin_set", ocre_gpio_wasm_set, "(iii)i", NULL}, - {"ocre_gpio_pin_get", ocre_gpio_wasm_get, "(ii)i", NULL}, - {"ocre_gpio_pin_toggle", ocre_gpio_wasm_toggle, "(ii)i", NULL}, - {"ocre_gpio_register_callback", ocre_gpio_wasm_register_callback, "(ii)i", NULL}, - {"ocre_gpio_unregister_callback", ocre_gpio_wasm_unregister_callback, "(ii)i", NULL}, - - {"ocre_gpio_configure_by_name", ocre_gpio_wasm_configure_by_name, "($i)i", NULL}, - {"ocre_gpio_set_by_name", ocre_gpio_wasm_set_by_name, "($i)i", NULL}, - {"ocre_gpio_get_by_name", ocre_gpio_wasm_get_by_name, "($)i", NULL}, - {"ocre_gpio_toggle_by_name", ocre_gpio_wasm_toggle_by_name, "($)i", NULL}, - {"ocre_gpio_register_callback_by_name", ocre_gpio_wasm_register_callback_by_name, "($)i", NULL}, - {"ocre_gpio_unregister_callback_by_name", ocre_gpio_wasm_unregister_callback_by_name, "($)i", NULL}, + {"ocre_gpio_init", ocre_gpio_wasm_init, "()i", NULL}, + {"ocre_gpio_configure", ocre_gpio_wasm_configure, "(iii)i", NULL}, + {"ocre_gpio_pin_set", ocre_gpio_wasm_set, "(iii)i", NULL}, + {"ocre_gpio_pin_get", ocre_gpio_wasm_get, "(ii)i", NULL}, + {"ocre_gpio_pin_toggle", ocre_gpio_wasm_toggle, "(ii)i", NULL}, + {"ocre_gpio_register_callback", ocre_gpio_wasm_register_callback, "(ii)i", NULL}, + {"ocre_gpio_unregister_callback", ocre_gpio_wasm_unregister_callback, "(ii)i", NULL}, + + {"ocre_gpio_configure_by_name", ocre_gpio_wasm_configure_by_name, "($i)i", NULL}, + {"ocre_gpio_set_by_name", ocre_gpio_wasm_set_by_name, "($i)i", NULL}, + {"ocre_gpio_get_by_name", ocre_gpio_wasm_get_by_name, "($)i", NULL}, + {"ocre_gpio_toggle_by_name", ocre_gpio_wasm_toggle_by_name, "($)i", NULL}, + {"ocre_gpio_register_callback_by_name", ocre_gpio_wasm_register_callback_by_name, "($)i", NULL}, + {"ocre_gpio_unregister_callback_by_name", ocre_gpio_wasm_unregister_callback_by_name, "($)i", NULL}, #endif }; diff --git a/src/ocre/api/ocre_api.h b/src/ocre/api/ocre_api.h index a0e8385f..391b5635 100644 --- a/src/ocre/api/ocre_api.h +++ b/src/ocre/api/ocre_api.h @@ -17,12 +17,12 @@ #endif struct _ocre_posix_utsname { - char sysname[OCRE_API_POSIX_BUF_SIZE]; - char nodename[OCRE_API_POSIX_BUF_SIZE]; - char release[OCRE_API_POSIX_BUF_SIZE]; - char version[OCRE_API_POSIX_BUF_SIZE]; - char machine[OCRE_API_POSIX_BUF_SIZE]; - char domainname[OCRE_API_POSIX_BUF_SIZE]; + char sysname[OCRE_API_POSIX_BUF_SIZE]; + char nodename[OCRE_API_POSIX_BUF_SIZE]; + char release[OCRE_API_POSIX_BUF_SIZE]; + char version[OCRE_API_POSIX_BUF_SIZE]; + char machine[OCRE_API_POSIX_BUF_SIZE]; + char domainname[OCRE_API_POSIX_BUF_SIZE]; }; int _ocre_posix_uname(wasm_exec_env_t exec_env, struct _ocre_posix_utsname *name); diff --git a/src/ocre/api/ocre_common.c b/src/ocre/api/ocre_common.c index 6b5dc93f..f8362fdd 100644 --- a/src/ocre/api/ocre_common.c +++ b/src/ocre/api/ocre_common.c @@ -27,8 +27,8 @@ LOG_MODULE_DECLARE(ocre_cs_component, OCRE_LOG_LEVEL); #include "ocre_common.h" typedef struct module_node { - ocre_module_context_t ctx; - core_snode_t node; + ocre_module_context_t ctx; + core_snode_t node; } module_node_t; static core_slist_t module_registry; @@ -42,8 +42,8 @@ bool ocre_event_queue_initialized = false; core_spinlock_t ocre_event_queue_lock; static struct cleanup_handler { - ocre_resource_type_t type; - ocre_cleanup_handler_t handler; + ocre_resource_type_t type; + ocre_cleanup_handler_t handler; } cleanup_handlers[OCRE_RESOURCE_TYPE_COUNT]; bool common_initialized = false; @@ -54,7 +54,7 @@ __thread wasm_module_inst_t *current_module_tls = NULL; #if EVENT_THREAD_POOL_SIZE > 0 // Arguments for event threads struct event_thread_args { - int index; // Thread index for identification or logging + int index; // Thread index for identification or logging }; static struct core_thread event_threads[EVENT_THREAD_POOL_SIZE]; // Flag to signal event threads to exit gracefully @@ -62,345 +62,328 @@ static volatile bool event_threads_exit = false; static struct event_thread_args event_args[EVENT_THREAD_POOL_SIZE]; // Event thread function to process events from the ring buffer -static void event_thread_fn(void *arg1) -{ - struct event_thread_args *args = (struct event_thread_args *)arg1; - // Initialize WASM runtime thread environment - wasm_runtime_init_thread_env(); - // Main event processing loop - // Do something in wasm - // Saved for future usage - // Clean up WASM runtime thread envirnment - wasm_runtime_destroy_thread_env(); +static void event_thread_fn(void *arg1) { + struct event_thread_args *args = (struct event_thread_args *)arg1; + // Initialize WASM runtime thread environment + wasm_runtime_init_thread_env(); + // Main event processing loop + // Do something in wasm + // Saved for future usage + // Clean up WASM runtime thread envirnment + wasm_runtime_destroy_thread_env(); } #endif int ocre_get_event(wasm_exec_env_t exec_env, uint32_t type_offset, uint32_t id_offset, uint32_t port_offset, - uint32_t state_offset, uint32_t extra_offset, uint32_t payload_len_offset) -{ - wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); - if (!module_inst) { - LOG_ERR("No module instance for exec_env\n"); - return -EINVAL; - } - - uint32_t *type_native = (uint32_t *)wasm_runtime_addr_app_to_native(module_inst, type_offset); - uint32_t *id_native = (uint32_t *)wasm_runtime_addr_app_to_native(module_inst, id_offset); - uint32_t *port_native = (uint32_t *)wasm_runtime_addr_app_to_native(module_inst, port_offset); - uint32_t *state_native = (uint32_t *)wasm_runtime_addr_app_to_native(module_inst, state_offset); - uint32_t *extra_native = (uint32_t *)wasm_runtime_addr_app_to_native(module_inst, extra_offset); - uint32_t *payload_len_native = (uint32_t *)wasm_runtime_addr_app_to_native(module_inst, payload_len_offset); - - if (!type_native || !id_native || !port_native || !state_native || !extra_native || !payload_len_native) { - LOG_ERR("Invalid offsets provided"); - return -EINVAL; - } - - ocre_event_t event; - int ret; - - /* Generic event queue implementation for both platforms */ - core_spinlock_key_t key = core_spinlock_lock(&ocre_event_queue_lock); - ret = core_eventq_peek(&ocre_event_queue, &event); - if (ret != 0) { - core_spinlock_unlock(&ocre_event_queue_lock, key); - return -ENOMSG; - } - - if (event.owner != module_inst) { - core_spinlock_unlock(&ocre_event_queue_lock, key); - return -EPERM; - } - - ret = core_eventq_get(&ocre_event_queue, &event); - if (ret != 0) { - core_spinlock_unlock(&ocre_event_queue_lock, key); - return -ENOENT; - } - - // Send event correctly to WASM - switch (event.type) { - case OCRE_RESOURCE_TYPE_TIMER: { - LOG_DBG("Retrieved Timer event timer_id=%u, owner=%p", event.data.timer_event.timer_id, - (void *)event.owner); - *type_native = event.type; - *id_native = event.data.timer_event.timer_id; - *port_native = 0; - *state_native = 0; - *extra_native = 0; - *payload_len_native = 0; - break; - } - case OCRE_RESOURCE_TYPE_GPIO: { - LOG_DBG("Retrieved Gpio event pin_id=%u, port=%u, state=%u, owner=%p", - event.data.gpio_event.pin_id, event.data.gpio_event.port, event.data.gpio_event.state, - (void *)event.owner); - *type_native = event.type; - *id_native = event.data.gpio_event.pin_id; - *port_native = event.data.gpio_event.port; - *state_native = event.data.gpio_event.state; - *extra_native = 0; - *payload_len_native = 0; - break; - } - case OCRE_RESOURCE_TYPE_SENSOR: { - // Not used as we don't use callbacks in sensor API yet - break; - } - case OCRE_RESOURCE_TYPE_MESSAGING: { - LOG_DBG("Retrieved Messaging event: message_id=%u, topic=%s, topic_offset=%u, content_type=%s, " - "content_type_offset=%u, payload_len=%d, owner=%p", - event.data.messaging_event.message_id, event.data.messaging_event.topic, - event.data.messaging_event.topic_offset, event.data.messaging_event.content_type, - event.data.messaging_event.content_type_offset, event.data.messaging_event.payload_len, - (void *)event.owner); - *type_native = event.type; - *id_native = event.data.messaging_event.message_id; - *port_native = event.data.messaging_event.topic_offset; - *state_native = event.data.messaging_event.content_type_offset; - *extra_native = event.data.messaging_event.payload_offset; - *payload_len_native = event.data.messaging_event.payload_len; - break; - } - /* - ================================= - Place to add more resource types - ================================= - */ - default: { - core_spinlock_unlock(&ocre_event_queue_lock, key); - LOG_ERR("Invalid event type: %u", event.type); - return -EINVAL; - } - } - core_spinlock_unlock(&ocre_event_queue_lock, key); - return 0; + uint32_t state_offset, uint32_t extra_offset, uint32_t payload_len_offset) { + wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); + if (!module_inst) { + LOG_ERR("No module instance for exec_env\n"); + return -EINVAL; + } + + uint32_t *type_native = (uint32_t *)wasm_runtime_addr_app_to_native(module_inst, type_offset); + uint32_t *id_native = (uint32_t *)wasm_runtime_addr_app_to_native(module_inst, id_offset); + uint32_t *port_native = (uint32_t *)wasm_runtime_addr_app_to_native(module_inst, port_offset); + uint32_t *state_native = (uint32_t *)wasm_runtime_addr_app_to_native(module_inst, state_offset); + uint32_t *extra_native = (uint32_t *)wasm_runtime_addr_app_to_native(module_inst, extra_offset); + uint32_t *payload_len_native = (uint32_t *)wasm_runtime_addr_app_to_native(module_inst, payload_len_offset); + + if (!type_native || !id_native || !port_native || !state_native || !extra_native || !payload_len_native) { + LOG_ERR("Invalid offsets provided"); + return -EINVAL; + } + + ocre_event_t event; + int ret; + + /* Generic event queue implementation for both platforms */ + core_spinlock_key_t key = core_spinlock_lock(&ocre_event_queue_lock); + ret = core_eventq_peek(&ocre_event_queue, &event); + if (ret != 0) { + core_spinlock_unlock(&ocre_event_queue_lock, key); + return -ENOMSG; + } + + if (event.owner != module_inst) { + core_spinlock_unlock(&ocre_event_queue_lock, key); + return -EPERM; + } + + ret = core_eventq_get(&ocre_event_queue, &event); + if (ret != 0) { + core_spinlock_unlock(&ocre_event_queue_lock, key); + return -ENOENT; + } + + // Send event correctly to WASM + switch (event.type) { + case OCRE_RESOURCE_TYPE_TIMER: { + LOG_DBG("Retrieved Timer event timer_id=%u, owner=%p", event.data.timer_event.timer_id, + (void *)event.owner); + *type_native = event.type; + *id_native = event.data.timer_event.timer_id; + *port_native = 0; + *state_native = 0; + *extra_native = 0; + *payload_len_native = 0; + break; + } + case OCRE_RESOURCE_TYPE_GPIO: { + LOG_DBG("Retrieved Gpio event pin_id=%u, port=%u, state=%u, owner=%p", event.data.gpio_event.pin_id, + event.data.gpio_event.port, event.data.gpio_event.state, (void *)event.owner); + *type_native = event.type; + *id_native = event.data.gpio_event.pin_id; + *port_native = event.data.gpio_event.port; + *state_native = event.data.gpio_event.state; + *extra_native = 0; + *payload_len_native = 0; + break; + } + case OCRE_RESOURCE_TYPE_SENSOR: { + // Not used as we don't use callbacks in sensor API yet + break; + } + case OCRE_RESOURCE_TYPE_MESSAGING: { + LOG_DBG("Retrieved Messaging event: message_id=%u, topic=%s, topic_offset=%u, content_type=%s, " + "content_type_offset=%u, payload_len=%d, owner=%p", + event.data.messaging_event.message_id, event.data.messaging_event.topic, + event.data.messaging_event.topic_offset, event.data.messaging_event.content_type, + event.data.messaging_event.content_type_offset, event.data.messaging_event.payload_len, + (void *)event.owner); + *type_native = event.type; + *id_native = event.data.messaging_event.message_id; + *port_native = event.data.messaging_event.topic_offset; + *state_native = event.data.messaging_event.content_type_offset; + *extra_native = event.data.messaging_event.payload_offset; + *payload_len_native = event.data.messaging_event.payload_len; + break; + } + /* + ================================= + Place to add more resource types + ================================= + */ + default: { + core_spinlock_unlock(&ocre_event_queue_lock, key); + LOG_ERR("Invalid event type: %u", event.type); + return -EINVAL; + } + } + core_spinlock_unlock(&ocre_event_queue_lock, key); + return 0; } -int ocre_common_init(void) -{ - static bool initialized = false; - if (initialized) { - LOG_INF("Common system already initialized"); - return 0; - } - - core_mutex_init(®istry_mutex); - core_slist_init(&module_registry); - - core_eventq_init(&ocre_event_queue, sizeof(ocre_event_t), SIZE_OCRE_EVENT_BUFFER); - - /* Purge any stale events from queue */ - ocre_event_t dummy; - while (core_eventq_get(&ocre_event_queue, &dummy) == 0) { - LOG_INF("Purged stale event from queue"); - } - - /* Temporary platform-specific initialization */ +int ocre_common_init(void) { + static bool initialized = false; + if (initialized) { + LOG_INF("Common system already initialized"); + return 0; + } + + core_mutex_init(®istry_mutex); + core_slist_init(&module_registry); + + core_eventq_init(&ocre_event_queue, sizeof(ocre_event_t), SIZE_OCRE_EVENT_BUFFER); + + /* Purge any stale events from queue */ + ocre_event_t dummy; + while (core_eventq_get(&ocre_event_queue, &dummy) == 0) { + LOG_INF("Purged stale event from queue"); + } + + /* Temporary platform-specific initialization */ #ifdef __ZEPHYR__ - /* No additional Zephyr-specific initialization needed */ + /* No additional Zephyr-specific initialization needed */ #else /* POSIX */ - pthread_mutex_init(&ocre_event_queue_lock.mutex, NULL); + pthread_mutex_init(&ocre_event_queue_lock.mutex, NULL); #endif - ocre_event_queue_initialized = true; + ocre_event_queue_initialized = true; #if EVENT_THREAD_POOL_SIZE > 0 - LOG_INF("ocre_event_queue initialized at %p, size=%d", (void *)&ocre_event_queue, sizeof(ocre_event_t)); - for (int i = 0; i < EVENT_THREAD_POOL_SIZE; i++) { - event_args[i].index = i; - char thread_name[16]; - snprintf(thread_name, sizeof(thread_name), "event_thread_%d", i); - int ret = core_thread_create(&event_threads[i], event_thread_fn, &event_args[i], thread_name, - EVENT_THREAD_STACK_SIZE, 5); - if (ret != 0) { - LOG_ERR("Failed to create thread for event %d", i); - return -1; - } - LOG_INF("Started event thread %s", thread_name); - } + LOG_INF("ocre_event_queue initialized at %p, size=%d", (void *)&ocre_event_queue, sizeof(ocre_event_t)); + for (int i = 0; i < EVENT_THREAD_POOL_SIZE; i++) { + event_args[i].index = i; + char thread_name[16]; + snprintf(thread_name, sizeof(thread_name), "event_thread_%d", i); + int ret = core_thread_create(&event_threads[i], event_thread_fn, &event_args[i], thread_name, + EVENT_THREAD_STACK_SIZE, 5); + if (ret != 0) { + LOG_ERR("Failed to create thread for event %d", i); + return -1; + } + LOG_INF("Started event thread %s", thread_name); + } #endif - initialized = true; - common_initialized = true; - - LOG_INF("OCRE common initialized successfully"); - return 0; + initialized = true; + common_initialized = true; + + LOG_INF("OCRE common initialized successfully"); + return 0; } -void ocre_common_shutdown(void) -{ +void ocre_common_shutdown(void) { #if EVENT_THREAD_POOL_SIZE > 0 - event_threads_exit = true; - for (int i = EVENT_THREAD_POOL_SIZE; i > 0; i--) { - event_args[i].index = i; - char thread_name[16]; - snprintf(thread_name, sizeof(thread_name), "event_thread_%d", i); - core_thread_destroy(&event_threads[i]); - } + event_threads_exit = true; + for (int i = EVENT_THREAD_POOL_SIZE; i > 0; i--) { + event_args[i].index = i; + char thread_name[16]; + snprintf(thread_name, sizeof(thread_name), "event_thread_%d", i); + core_thread_destroy(&event_threads[i]); + } #endif - common_initialized = false; - LOG_INF("OCRE common shutdown successfully"); + common_initialized = false; + LOG_INF("OCRE common shutdown successfully"); } -int ocre_register_cleanup_handler(ocre_resource_type_t type, ocre_cleanup_handler_t handler) -{ - if (type >= OCRE_RESOURCE_TYPE_COUNT) { - LOG_ERR("Invalid resource type: %d", type); - return -EINVAL; - } - cleanup_handlers[type] = (struct cleanup_handler){type, handler}; - LOG_INF("Registered cleanup handler for type %d", type); - return 0; +int ocre_register_cleanup_handler(ocre_resource_type_t type, ocre_cleanup_handler_t handler) { + if (type >= OCRE_RESOURCE_TYPE_COUNT) { + LOG_ERR("Invalid resource type: %d", type); + return -EINVAL; + } + cleanup_handlers[type] = (struct cleanup_handler){type, handler}; + LOG_INF("Registered cleanup handler for type %d", type); + return 0; } -int ocre_register_module(wasm_module_inst_t module_inst) -{ - if (!module_inst) { - LOG_ERR("Null module instance"); - return -EINVAL; - } - module_node_t *node = core_malloc(sizeof(module_node_t)); - if (!node) { - LOG_ERR("Failed to allocate module node"); - return -ENOMEM; - } - node->ctx.inst = module_inst; - node->ctx.exec_env = wasm_runtime_create_exec_env(module_inst, OCRE_WASM_STACK_SIZE); - if (!node->ctx.exec_env) { - LOG_ERR("Failed to create exec env for module %p", (void *)module_inst); - core_free(node); - return -ENOMEM; - } - node->ctx.in_use = true; - node->ctx.last_activity = core_uptime_get(); - memset(node->ctx.resource_count, 0, sizeof(node->ctx.resource_count)); - memset(node->ctx.dispatchers, 0, sizeof(node->ctx.dispatchers)); - - core_mutex_lock(®istry_mutex); - core_slist_append(&module_registry, &node->node); - core_mutex_unlock(®istry_mutex); - - LOG_INF("Module registered: %p", (void *)module_inst); - return 0; +int ocre_register_module(wasm_module_inst_t module_inst) { + if (!module_inst) { + LOG_ERR("Null module instance"); + return -EINVAL; + } + module_node_t *node = core_malloc(sizeof(module_node_t)); + if (!node) { + LOG_ERR("Failed to allocate module node"); + return -ENOMEM; + } + node->ctx.inst = module_inst; + node->ctx.exec_env = wasm_runtime_create_exec_env(module_inst, OCRE_WASM_STACK_SIZE); + if (!node->ctx.exec_env) { + LOG_ERR("Failed to create exec env for module %p", (void *)module_inst); + core_free(node); + return -ENOMEM; + } + node->ctx.in_use = true; + node->ctx.last_activity = core_uptime_get(); + memset(node->ctx.resource_count, 0, sizeof(node->ctx.resource_count)); + memset(node->ctx.dispatchers, 0, sizeof(node->ctx.dispatchers)); + + core_mutex_lock(®istry_mutex); + core_slist_append(&module_registry, &node->node); + core_mutex_unlock(®istry_mutex); + + LOG_INF("Module registered: %p", (void *)module_inst); + return 0; } -void ocre_unregister_module(wasm_module_inst_t module_inst) -{ - if (!module_inst) { - LOG_ERR("Null module instance"); - return; - } - - core_mutex_lock(®istry_mutex); - module_node_t *node, *tmp; - module_node_t *prev = NULL; - CORE_SLIST_FOR_EACH_CONTAINER_SAFE(&module_registry, node, tmp, node) - { - if (node->ctx.inst == module_inst) { - ocre_cleanup_module_resources(module_inst); - if (node->ctx.exec_env) { - wasm_runtime_destroy_exec_env(node->ctx.exec_env); - } - core_slist_remove(&module_registry, prev ? &prev->node : NULL, &node->node); - core_free(node); - LOG_INF("Module unregistered: %p", (void *)module_inst); - break; - } - prev = node; - } - core_mutex_unlock(®istry_mutex); +void ocre_unregister_module(wasm_module_inst_t module_inst) { + if (!module_inst) { + LOG_ERR("Null module instance"); + return; + } + + core_mutex_lock(®istry_mutex); + module_node_t *node, *tmp; + module_node_t *prev = NULL; + CORE_SLIST_FOR_EACH_CONTAINER_SAFE(&module_registry, node, tmp, node) { + if (node->ctx.inst == module_inst) { + ocre_cleanup_module_resources(module_inst); + if (node->ctx.exec_env) { + wasm_runtime_destroy_exec_env(node->ctx.exec_env); + } + core_slist_remove(&module_registry, prev ? &prev->node : NULL, &node->node); + core_free(node); + LOG_INF("Module unregistered: %p", (void *)module_inst); + break; + } + prev = node; + } + core_mutex_unlock(®istry_mutex); } -ocre_module_context_t *ocre_get_module_context(wasm_module_inst_t module_inst) -{ - if (!module_inst) { - LOG_ERR("Null module instance"); - return NULL; - } - core_mutex_lock(®istry_mutex); - for (core_snode_t *current = module_registry.head; current != NULL; current = current->next) { - module_node_t *node = (module_node_t *)((char *)current - offsetof(module_node_t, node)); - if (node->ctx.inst == module_inst) { - node->ctx.last_activity = core_uptime_get(); - core_mutex_unlock(®istry_mutex); - return &node->ctx; - } - } - core_mutex_unlock(®istry_mutex); - LOG_ERR("Module context not found for %p", (void *)module_inst); - return NULL; +ocre_module_context_t *ocre_get_module_context(wasm_module_inst_t module_inst) { + if (!module_inst) { + LOG_ERR("Null module instance"); + return NULL; + } + core_mutex_lock(®istry_mutex); + for (core_snode_t *current = module_registry.head; current != NULL; current = current->next) { + module_node_t *node = (module_node_t *)((char *)current - offsetof(module_node_t, node)); + if (node->ctx.inst == module_inst) { + node->ctx.last_activity = core_uptime_get(); + core_mutex_unlock(®istry_mutex); + return &node->ctx; + } + } + core_mutex_unlock(®istry_mutex); + LOG_ERR("Module context not found for %p", (void *)module_inst); + return NULL; } -int ocre_register_dispatcher(wasm_exec_env_t exec_env, ocre_resource_type_t type, const char *function_name) -{ - if (!exec_env || !function_name || type >= OCRE_RESOURCE_TYPE_COUNT) { - LOG_ERR("Invalid dispatcher params: exec_env=%p, type=%d, func=%s", (void *)exec_env, type, - function_name ? function_name : "null"); - return -EINVAL; - } - - wasm_module_inst_t module_inst = - current_module_tls ? *current_module_tls : wasm_runtime_get_module_inst(exec_env); - - if (!module_inst) { - LOG_ERR("No module instance for event type %d", type); - return -EINVAL; - } - ocre_module_context_t *ctx = ocre_get_module_context(module_inst); - if (!ctx) { - LOG_ERR("Module context not found for %p", (void *)module_inst); - return -EINVAL; - } - LOG_DBG("Attempting to lookup function '%s' in module %p", function_name, (void *)module_inst); - wasm_function_inst_t func = wasm_runtime_lookup_function(module_inst, function_name); - if (!func) { - LOG_ERR("Function %s not found in module %p", function_name, (void *)module_inst); - return -EINVAL; - } - core_mutex_lock(®istry_mutex); - ctx->dispatchers[type] = func; - core_mutex_unlock(®istry_mutex); - LOG_INF("Registered dispatcher for type %d: %s", type, function_name); - return 0; +int ocre_register_dispatcher(wasm_exec_env_t exec_env, ocre_resource_type_t type, const char *function_name) { + if (!exec_env || !function_name || type >= OCRE_RESOURCE_TYPE_COUNT) { + LOG_ERR("Invalid dispatcher params: exec_env=%p, type=%d, func=%s", (void *)exec_env, type, + function_name ? function_name : "null"); + return -EINVAL; + } + + wasm_module_inst_t module_inst = current_module_tls ? *current_module_tls : wasm_runtime_get_module_inst(exec_env); + + if (!module_inst) { + LOG_ERR("No module instance for event type %d", type); + return -EINVAL; + } + ocre_module_context_t *ctx = ocre_get_module_context(module_inst); + if (!ctx) { + LOG_ERR("Module context not found for %p", (void *)module_inst); + return -EINVAL; + } + LOG_DBG("Attempting to lookup function '%s' in module %p", function_name, (void *)module_inst); + wasm_function_inst_t func = wasm_runtime_lookup_function(module_inst, function_name); + if (!func) { + LOG_ERR("Function %s not found in module %p", function_name, (void *)module_inst); + return -EINVAL; + } + core_mutex_lock(®istry_mutex); + ctx->dispatchers[type] = func; + core_mutex_unlock(®istry_mutex); + LOG_INF("Registered dispatcher for type %d: %s", type, function_name); + return 0; } -uint32_t ocre_get_resource_count(wasm_module_inst_t module_inst, ocre_resource_type_t type) -{ - ocre_module_context_t *ctx = ocre_get_module_context(module_inst); - return ctx ? ctx->resource_count[type] : 0; +uint32_t ocre_get_resource_count(wasm_module_inst_t module_inst, ocre_resource_type_t type) { + ocre_module_context_t *ctx = ocre_get_module_context(module_inst); + return ctx ? ctx->resource_count[type] : 0; } -void ocre_increment_resource_count(wasm_module_inst_t module_inst, ocre_resource_type_t type) -{ - ocre_module_context_t *ctx = ocre_get_module_context(module_inst); - if (ctx && type < OCRE_RESOURCE_TYPE_COUNT) { - core_mutex_lock(®istry_mutex); - ctx->resource_count[type]++; - core_mutex_unlock(®istry_mutex); - LOG_INF("Incremented resource count: type=%d, count=%d", type, ctx->resource_count[type]); - } +void ocre_increment_resource_count(wasm_module_inst_t module_inst, ocre_resource_type_t type) { + ocre_module_context_t *ctx = ocre_get_module_context(module_inst); + if (ctx && type < OCRE_RESOURCE_TYPE_COUNT) { + core_mutex_lock(®istry_mutex); + ctx->resource_count[type]++; + core_mutex_unlock(®istry_mutex); + LOG_INF("Incremented resource count: type=%d, count=%d", type, ctx->resource_count[type]); + } } -void ocre_decrement_resource_count(wasm_module_inst_t module_inst, ocre_resource_type_t type) -{ - ocre_module_context_t *ctx = ocre_get_module_context(module_inst); - if (ctx && type < OCRE_RESOURCE_TYPE_COUNT && ctx->resource_count[type] > 0) { - core_mutex_lock(®istry_mutex); - ctx->resource_count[type]--; - core_mutex_unlock(®istry_mutex); - LOG_INF("Decremented resource count: type=%d, count=%d", type, ctx->resource_count[type]); - } +void ocre_decrement_resource_count(wasm_module_inst_t module_inst, ocre_resource_type_t type) { + ocre_module_context_t *ctx = ocre_get_module_context(module_inst); + if (ctx && type < OCRE_RESOURCE_TYPE_COUNT && ctx->resource_count[type] > 0) { + core_mutex_lock(®istry_mutex); + ctx->resource_count[type]--; + core_mutex_unlock(®istry_mutex); + LOG_INF("Decremented resource count: type=%d, count=%d", type, ctx->resource_count[type]); + } } -void ocre_cleanup_module_resources(wasm_module_inst_t module_inst) -{ - for (int i = 0; i < OCRE_RESOURCE_TYPE_COUNT; i++) { - if (cleanup_handlers[i].handler) { - cleanup_handlers[i].handler(module_inst); - } - } +void ocre_cleanup_module_resources(wasm_module_inst_t module_inst) { + for (int i = 0; i < OCRE_RESOURCE_TYPE_COUNT; i++) { + if (cleanup_handlers[i].handler) { + cleanup_handlers[i].handler(module_inst); + } + } } -wasm_module_inst_t ocre_get_current_module(void) -{ - return current_module_tls ? *current_module_tls : NULL; +wasm_module_inst_t ocre_get_current_module(void) { + return current_module_tls ? *current_module_tls : NULL; } diff --git a/src/ocre/api/ocre_common.h b/src/ocre/api/ocre_common.h index 97d7c5f3..95be03a9 100644 --- a/src/ocre/api/ocre_common.h +++ b/src/ocre/api/ocre_common.h @@ -16,39 +16,40 @@ #define OCRE_EVENT_THREAD_STACK_SIZE 2048 #define OCRE_EVENT_THREAD_PRIORITY 5 -#define OCRE_WASM_STACK_SIZE 16384 -#define EVENT_THREAD_POOL_SIZE 0 +#define OCRE_WASM_STACK_SIZE 16384 +#define EVENT_THREAD_POOL_SIZE 0 extern bool common_initialized; extern bool ocre_event_queue_initialized; extern __thread wasm_module_inst_t *current_module_tls; -extern char *ocre_event_queue_buffer_ptr; // Defined in ocre_common.c +extern char *ocre_event_queue_buffer_ptr; // Defined in ocre_common.c /* External declarations for unified event queue */ -extern core_eventq_t ocre_event_queue; // Defined in ocre_common.c -extern core_spinlock_t ocre_event_queue_lock; // Defined in ocre_common.c +extern core_eventq_t ocre_event_queue; // Defined in ocre_common.c +extern core_spinlock_t ocre_event_queue_lock; // Defined in ocre_common.c + /** * @brief Enumeration of OCRE resource types. */ typedef enum { - OCRE_RESOURCE_TYPE_TIMER, ///< Timer resource - OCRE_RESOURCE_TYPE_GPIO, ///< GPIO resource - OCRE_RESOURCE_TYPE_SENSOR, ///< Sensor resource - OCRE_RESOURCE_TYPE_MESSAGING, ///< Messaging resource - OCRE_RESOURCE_TYPE_COUNT ///< Total number of resource types + OCRE_RESOURCE_TYPE_TIMER, ///< Timer resource + OCRE_RESOURCE_TYPE_GPIO, ///< GPIO resource + OCRE_RESOURCE_TYPE_SENSOR, ///< Sensor resource + OCRE_RESOURCE_TYPE_MESSAGING, ///< Messaging resource + OCRE_RESOURCE_TYPE_COUNT ///< Total number of resource types } ocre_resource_type_t; /** * @brief Structure representing the context of an OCRE module. */ typedef struct { - wasm_module_inst_t inst; ///< WASM module instance - wasm_exec_env_t exec_env; ///< WASM execution environment - bool in_use; ///< Flag indicating if the module is in use - uint32_t last_activity; ///< Timestamp of the last activity - uint32_t resource_count[OCRE_RESOURCE_TYPE_COUNT]; ///< Count of resources per type - wasm_function_inst_t dispatchers[OCRE_RESOURCE_TYPE_COUNT]; ///< Event dispatchers per resource type + wasm_module_inst_t inst; ///< WASM module instance + wasm_exec_env_t exec_env; ///< WASM execution environment + bool in_use; ///< Flag indicating if the module is in use + uint32_t last_activity; ///< Timestamp of the last activity + uint32_t resource_count[OCRE_RESOURCE_TYPE_COUNT]; ///< Count of resources per type + wasm_function_inst_t dispatchers[OCRE_RESOURCE_TYPE_COUNT]; ///< Event dispatchers per resource type } ocre_module_context_t; /** @@ -62,38 +63,38 @@ typedef void (*ocre_cleanup_handler_t)(wasm_module_inst_t module_inst); * @brief Structure representing an OCRE event for dispatching. */ typedef struct { - union { - struct { - uint32_t timer_id; ///< Timer ID - } timer_event; ///< Timer event data - struct { - uint32_t pin_id; ///< GPIO pin ID - uint32_t port; ///< GPIO port - uint32_t state; ///< GPIO state - } gpio_event; ///< GPIO event data - struct { - uint32_t sensor_id; ///< Sensor ID - uint32_t channel; ///< Sensor channel - uint32_t value; ///< Sensor value - } sensor_event; ///< Sensor event data - struct { - uint32_t message_id; ///< Message ID - char *topic; ///< Message topic - uint32_t topic_offset; ///< Message topic offset - char *content_type; ///< Message content type - uint32_t content_type_offset; ///< Message content type offset - void *payload; ///< Message payload - uint32_t payload_offset; ///< Message payload offset - uint32_t payload_len; ///< Payload length - } messaging_event; ///< Messaging event data - /* - ============================= - Place to add more event data - ============================= - */ - } data; ///< Union of event data - wasm_module_inst_t owner; ///< Owner module instance - ocre_resource_type_t type; ///< Type of the event + union { + struct { + uint32_t timer_id; ///< Timer ID + } timer_event; ///< Timer event data + struct { + uint32_t pin_id; ///< GPIO pin ID + uint32_t port; ///< GPIO port + uint32_t state; ///< GPIO state + } gpio_event; ///< GPIO event data + struct { + uint32_t sensor_id; ///< Sensor ID + uint32_t channel; ///< Sensor channel + uint32_t value; ///< Sensor value + } sensor_event; ///< Sensor event data + struct { + uint32_t message_id; ///< Message ID + char *topic; ///< Message topic + uint32_t topic_offset; ///< Message topic offset + char *content_type; ///< Message content type + uint32_t content_type_offset; ///< Message content type offset + void *payload; ///< Message payload + uint32_t payload_offset; ///< Message payload offset + uint32_t payload_len; ///< Payload length + } messaging_event; ///< Messaging event data + /* + ============================= + Place to add more event data + ============================= + */ + } data; ///< Union of event data + wasm_module_inst_t owner; ///< Owner module instance + ocre_resource_type_t type; ///< Type of the event } ocre_event_t; /** @@ -199,7 +200,7 @@ wasm_module_inst_t ocre_get_current_module(void); * @return 0 on success, negative error code on failure. */ int ocre_get_event(wasm_exec_env_t exec_env, uint32_t type_offset, uint32_t id_offset, uint32_t port_offset, - uint32_t state_offset, uint32_t extra_offset, uint32_t payload_len_offset); + uint32_t state_offset, uint32_t extra_offset, uint32_t payload_len_offset); void ocre_common_shutdown(void); diff --git a/src/ocre/component/component.c b/src/ocre/component/component.c index 10849e52..daa6121b 100644 --- a/src/ocre/component/component.c +++ b/src/ocre/component/component.c @@ -10,14 +10,12 @@ #include "ocre_core_external.h" #include "component.h" -void ocre_component_init(struct ocre_component *component) -{ - core_mq_init(&component->msgq, "/ocre_component_msgq", sizeof(struct ocre_message), MSG_QUEUE_DEPTH); +void ocre_component_init(struct ocre_component *component) { + core_mq_init(&component->msgq, "/ocre_component_msgq", sizeof(struct ocre_message), MSG_QUEUE_DEPTH); } -int ocre_component_send(struct ocre_component *component, struct ocre_message *msg) -{ - int ret = core_mq_send(&component->msgq, msg, sizeof(struct ocre_message)); +int ocre_component_send(struct ocre_component *component, struct ocre_message *msg) { + int ret = core_mq_send(&component->msgq, msg, sizeof(struct ocre_message)); - return ret; + return ret; } diff --git a/src/ocre/component/component.h b/src/ocre/component/component.h index d11f8a18..b6d96e7a 100644 --- a/src/ocre/component/component.h +++ b/src/ocre/component/component.h @@ -15,12 +15,12 @@ #define MSG_QUEUE_DEPTH 10 #define COMPONENT_SEND_SIMPLE(c, e) \ - struct ocre_message _msg = {.event = e}; \ - ocre_component_send(c, &_msg) + struct ocre_message _msg = {.event = e}; \ + ocre_component_send(c, &_msg) struct ocre_component { - struct ocre_message msg; /*!< Message struct for reading messages into */ - core_mq_t msgq; /*!< Message queue to read from */ + struct ocre_message msg; /*!< Message struct for reading messages into */ + core_mq_t msgq; /*!< Message queue to read from */ }; void ocre_component_init(struct ocre_component *component); diff --git a/src/ocre/components/container_supervisor/cs_main.c b/src/ocre/components/container_supervisor/cs_main.c index 85ec7551..2727572f 100644 --- a/src/ocre/components/container_supervisor/cs_main.c +++ b/src/ocre/components/container_supervisor/cs_main.c @@ -11,42 +11,38 @@ LOG_MODULE_REGISTER(ocre_cs_component, OCRE_LOG_LEVEL); -#define OCRE_CS_THREAD_PRIORITY 0 +#define OCRE_CS_THREAD_PRIORITY 0 static core_thread_t ocre_cs_thread; static int ocre_cs_thread_initialized = 0; -static void ocre_cs_main(void *ctx) -{ - wasm_runtime_init_thread_env(); - LOG_INF("Container Supervisor started."); - int ret = _ocre_cs_run(ctx); - LOG_ERR("Container Supervisor exited: %d", ret); - wasm_runtime_destroy_thread_env(); +static void ocre_cs_main(void *ctx) { + wasm_runtime_init_thread_env(); + LOG_INF("Container Supervisor started."); + int ret = _ocre_cs_run(ctx); + LOG_ERR("Container Supervisor exited: %d", ret); + wasm_runtime_destroy_thread_env(); } // Function to start the thread -void start_ocre_cs_thread(ocre_cs_ctx *ctx) -{ - if (ocre_cs_thread_initialized) { - LOG_WRN("Container Supervisor thread is already running."); - return; - } - int ret = core_thread_create(&ocre_cs_thread, ocre_cs_main, ctx, "Ocre Container Supervisor", - OCRE_CS_THREAD_STACK_SIZE, OCRE_CS_THREAD_PRIORITY); - if (ret != 0) { - LOG_ERR("Failed to create Container Supervisor thread: %d", ret); - return; - } - ocre_cs_thread_initialized = 1; +void start_ocre_cs_thread(ocre_cs_ctx *ctx) { + if (ocre_cs_thread_initialized) { + LOG_WRN("Container Supervisor thread is already running."); + return; + } + int ret = core_thread_create(&ocre_cs_thread, ocre_cs_main, ctx, "Ocre Container Supervisor", OCRE_CS_THREAD_STACK_SIZE, OCRE_CS_THREAD_PRIORITY); + if (ret != 0) { + LOG_ERR("Failed to create Container Supervisor thread: %d", ret); + return; + } + ocre_cs_thread_initialized = 1; } -void destroy_ocre_cs_thread(void) -{ - if (!ocre_cs_thread_initialized) { - LOG_ERR("Container Supervisor thread is not running.\n"); - return; - } - core_thread_destroy(&ocre_cs_thread); - ocre_cs_thread_initialized = 0; +void destroy_ocre_cs_thread(void) { + if (!ocre_cs_thread_initialized) { + LOG_ERR("Container Supervisor thread is not running.\n"); + return; + } + core_thread_destroy(&ocre_cs_thread); + ocre_cs_thread_initialized = 0; } diff --git a/src/ocre/components/container_supervisor/cs_sm.c b/src/ocre/components/container_supervisor/cs_sm.c index 275d7bf9..9f2bc585 100644 --- a/src/ocre/components/container_supervisor/cs_sm.c +++ b/src/ocre/components/container_supervisor/cs_sm.c @@ -20,160 +20,150 @@ struct ocre_component ocre_cs_component; state_machine_t ocre_cs_state_machine; /* State event handlers */ -static void runtime_uninitialized_entry(void *o) -{ +static void runtime_uninitialized_entry(void *o) { #if OCRE_CS_DEBUG_ON - LOG_INF("HELLO runtime_uninitialized_entry"); + LOG_INF("HELLO runtime_uninitialized_entry"); #endif - struct ocre_message event = {.event = EVENT_CS_INITIALIZE}; - ocre_component_send(&ocre_cs_component, &event); + struct ocre_message event = {.event = EVENT_CS_INITIALIZE}; + ocre_component_send(&ocre_cs_component, &event); } -static enum smf_state_result runtime_uninitialized_run(void *o) -{ +static enum smf_state_result runtime_uninitialized_run(void *o) { #if OCRE_CS_DEBUG_ON - LOG_INF("HELLO runtime_uninitialized_run"); + LOG_INF("HELLO runtime_uninitialized_run"); #endif - struct ocre_message *msg = SM_GET_EVENT(o); + struct ocre_message *msg = SM_GET_EVENT(o); - switch (msg->event) { - case EVENT_CS_INITIALIZE: + switch (msg->event) { + case EVENT_CS_INITIALIZE: #if OCRE_CS_DEBUG_ON - LOG_INF("Transitioning from state STATE_RUNTIME_UNINITIALIZED_RUN to state " - "STATE_RUNTIME_RUNNING"); + LOG_INF("Transitioning from state STATE_RUNTIME_UNINITIALIZED_RUN to state STATE_RUNTIME_RUNNING"); #endif - sm_transition(&ocre_cs_state_machine, STATE_RUNTIME_RUNNING); - break; - default: - break; - } - SM_MARK_EVENT_HANDLED(o); - return SMF_EVENT_HANDLED; + sm_transition(&ocre_cs_state_machine, STATE_RUNTIME_RUNNING); + break; + default: + break; + } + SM_MARK_EVENT_HANDLED(o); + return SMF_EVENT_HANDLED; } -static void runtime_running_entry(void *o) -{ +static void runtime_running_entry(void *o) { #if OCRE_CS_DEBUG_ON - LOG_INF("HELLO runtime_running_entry"); + LOG_INF("HELLO runtime_running_entry"); #endif } -static enum smf_state_result runtime_running_run(void *o) -{ +static enum smf_state_result runtime_running_run(void *o) { #if OCRE_CS_DEBUG_ON - LOG_INF("HELLO runtime_running_run"); + LOG_INF("HELLO runtime_running_run"); #endif - struct ocre_message *msg = SM_GET_EVENT(o); - ocre_cs_ctx *ctx = SM_GET_CUSTOM_CTX(o); - ocre_container_runtime_cb callback = NULL; - switch (msg->event) { - case EVENT_CREATE_CONTAINER: { - LOG_INF("EVENT_CREATE_CONTAINER"); - - if (msg->containerId < 0 || msg->containerId >= CONFIG_MAX_CONTAINERS) { - LOG_ERR("Invalid container ID: %d", msg->containerId); - break; - } - - if (CS_create_container(&ctx->containers[msg->containerId]) == CONTAINER_STATUS_CREATED) { - LOG_INF("Created container in slot:%d", msg->containerId); - } else { - LOG_ERR("Failed to create container in slot:%d", msg->containerId); - } - break; - } - case EVENT_RUN_CONTAINER: { - LOG_INF("EVENT_RUN_CONTAINER"); - - if (msg->containerId < 0 || msg->containerId >= CONFIG_MAX_CONTAINERS) { - LOG_ERR("Invalid container ID: %d", msg->containerId); - break; - } - - if (CS_run_container(&ctx->containers[msg->containerId]) == CONTAINER_STATUS_RUNNING) { - LOG_INF("Started container in slot:%d", msg->containerId); - } else { - LOG_ERR("Failed to run container in slot:%d", msg->containerId); - } - break; - } - case EVENT_STOP_CONTAINER: { - LOG_INF("EVENT_STOP_CONTAINER"); - - if (msg->containerId < 0 || msg->containerId >= CONFIG_MAX_CONTAINERS) { - LOG_ERR("Invalid container ID: %d", msg->containerId); - break; - } - - if (CS_stop_container(&ctx->containers[msg->containerId], callback) == - CONTAINER_STATUS_STOPPED) { - LOG_INF("Stopped container in slot:%d", msg->containerId); - } else { - LOG_ERR("Failed to stop container in slot:%d", msg->containerId); - } - break; - } - case EVENT_DESTROY_CONTAINER: { - LOG_INF("EVENT_DESTROY_CONTAINER"); - - if (msg->containerId < 0 || msg->containerId >= CONFIG_MAX_CONTAINERS) { - LOG_ERR("Invalid container ID: %d", msg->containerId); - break; - } - - if (CS_destroy_container(&ctx->containers[msg->containerId], callback) == - CONTAINER_STATUS_DESTROYED) { - LOG_INF("Destroyed container in slot:%d", msg->containerId); - } else { - LOG_ERR("Failed to destroy container in slot:%d", msg->containerId); - } - break; - } - case EVENT_RESTART_CONTAINER: { - LOG_INF("EVENT_RESTART_CONTAINER"); - if (msg->containerId < 0 || msg->containerId >= CONFIG_MAX_CONTAINERS) { - LOG_ERR("Invalid container ID: %d", msg->containerId); - break; - } - - if (CS_restart_container(&ctx->containers[msg->containerId], callback) == - CONTAINER_STATUS_RUNNING) { - LOG_INF("Container in slot:%d restarted successfully", msg->containerId); - } else { - LOG_ERR("Failed to restart container in slot:%d", msg->containerId); - } - break; - } - case EVENT_CS_DESTROY: - LOG_INF("EVENT_CS_DESTROY"); - sm_transition(&ocre_cs_state_machine, STATE_RUNTIME_UNINITIALIZED); - break; - default: - break; - } - - SM_MARK_EVENT_HANDLED(o); - return SMF_EVENT_HANDLED; + struct ocre_message *msg = SM_GET_EVENT(o); + ocre_cs_ctx *ctx = SM_GET_CUSTOM_CTX(o); + ocre_container_runtime_cb callback = NULL; + switch (msg->event) { + case EVENT_CREATE_CONTAINER: { + LOG_INF("EVENT_CREATE_CONTAINER"); + + if (msg->containerId < 0 || msg->containerId >= CONFIG_MAX_CONTAINERS) { + LOG_ERR("Invalid container ID: %d", msg->containerId); + break; + } + + if (CS_create_container(&ctx->containers[msg->containerId]) == CONTAINER_STATUS_CREATED) { + LOG_INF("Created container in slot:%d", msg->containerId); + } else { + LOG_ERR("Failed to create container in slot:%d", msg->containerId); + } + break; + } + case EVENT_RUN_CONTAINER: { + LOG_INF("EVENT_RUN_CONTAINER"); + + if (msg->containerId < 0 || msg->containerId >= CONFIG_MAX_CONTAINERS) { + LOG_ERR("Invalid container ID: %d", msg->containerId); + break; + } + + if (CS_run_container(&ctx->containers[msg->containerId]) == CONTAINER_STATUS_RUNNING) { + LOG_INF("Started container in slot:%d", msg->containerId); + } else { + LOG_ERR("Failed to run container in slot:%d", msg->containerId); + } + break; + } + case EVENT_STOP_CONTAINER: { + LOG_INF("EVENT_STOP_CONTAINER"); + + if (msg->containerId < 0 || msg->containerId >= CONFIG_MAX_CONTAINERS) { + LOG_ERR("Invalid container ID: %d", msg->containerId); + break; + } + + if (CS_stop_container(&ctx->containers[msg->containerId], callback) == CONTAINER_STATUS_STOPPED) { + LOG_INF("Stopped container in slot:%d", msg->containerId); + } else { + LOG_ERR("Failed to stop container in slot:%d", msg->containerId); + } + break; + } + case EVENT_DESTROY_CONTAINER: { + LOG_INF("EVENT_DESTROY_CONTAINER"); + + if (msg->containerId < 0 || msg->containerId >= CONFIG_MAX_CONTAINERS) { + LOG_ERR("Invalid container ID: %d", msg->containerId); + break; + } + + if (CS_destroy_container(&ctx->containers[msg->containerId], callback) == CONTAINER_STATUS_DESTROYED) { + LOG_INF("Destroyed container in slot:%d", msg->containerId); + } else { + LOG_ERR("Failed to destroy container in slot:%d", msg->containerId); + } + break; + } + case EVENT_RESTART_CONTAINER: { + LOG_INF("EVENT_RESTART_CONTAINER"); + if (msg->containerId < 0 || msg->containerId >= CONFIG_MAX_CONTAINERS) { + LOG_ERR("Invalid container ID: %d", msg->containerId); + break; + } + + if (CS_restart_container(&ctx->containers[msg->containerId], callback) == CONTAINER_STATUS_RUNNING) { + LOG_INF("Container in slot:%d restarted successfully", msg->containerId); + } else { + LOG_ERR("Failed to restart container in slot:%d", msg->containerId); + } + break; + } + case EVENT_CS_DESTROY: + LOG_INF("EVENT_CS_DESTROY"); + sm_transition(&ocre_cs_state_machine, STATE_RUNTIME_UNINITIALIZED); + break; + default: + break; + } + + SM_MARK_EVENT_HANDLED(o); + return SMF_EVENT_HANDLED; } -static enum smf_state_result runtime_error_run(void *o) -{ +static enum smf_state_result runtime_error_run(void *o) { #if OCRE_CS_DEBUG_ON - LOG_INF("HELLO runtime_error_run"); + LOG_INF("HELLO runtime_error_run"); #endif - return SMF_EVENT_HANDLED; + return SMF_EVENT_HANDLED; } static const struct smf_state hsm[] = { - [STATE_RUNTIME_UNINITIALIZED] = - SMF_CREATE_STATE(runtime_uninitialized_entry, runtime_uninitialized_run, NULL, NULL, NULL), - [STATE_RUNTIME_RUNNING] = SMF_CREATE_STATE(runtime_running_entry, runtime_running_run, NULL, NULL, NULL), - [STATE_RUNTIME_ERROR] = SMF_CREATE_STATE(NULL, runtime_error_run, NULL, NULL, NULL)}; + [STATE_RUNTIME_UNINITIALIZED] = + SMF_CREATE_STATE(runtime_uninitialized_entry, runtime_uninitialized_run, NULL, NULL, NULL), + [STATE_RUNTIME_RUNNING] = SMF_CREATE_STATE(runtime_running_entry, runtime_running_run, NULL, NULL, NULL), + [STATE_RUNTIME_ERROR] = SMF_CREATE_STATE(NULL, runtime_error_run, NULL, NULL, NULL)}; // Entry point for running the state machine -int _ocre_cs_run(ocre_cs_ctx *ctx) -{ - ocre_component_init(&ocre_cs_component); - sm_init(&ocre_cs_state_machine, &ocre_cs_component.msgq, &ocre_cs_component.msg, ctx, hsm); - return sm_run(&ocre_cs_state_machine, STATE_RUNTIME_UNINITIALIZED); +int _ocre_cs_run(ocre_cs_ctx *ctx) { + ocre_component_init(&ocre_cs_component); + sm_init(&ocre_cs_state_machine, &ocre_cs_component.msgq, &ocre_cs_component.msg, ctx, hsm); + return sm_run(&ocre_cs_state_machine, STATE_RUNTIME_UNINITIALIZED); } diff --git a/src/ocre/components/container_supervisor/cs_sm.h b/src/ocre/components/container_supervisor/cs_sm.h index 3a323949..4ba02bc3 100644 --- a/src/ocre/components/container_supervisor/cs_sm.h +++ b/src/ocre/components/container_supervisor/cs_sm.h @@ -18,28 +18,28 @@ extern struct ocre_component ocre_cs_component; extern state_machine_t ocre_cs_state_machine; // TODO This needs to get encapsulated into the - // sm. it's only here so components can operate - // timers. timers need to be encapsulated. + // sm. it's only here so components can operate + // timers. timers need to be encapsulated. enum CONTAINER_RUNTIME_STATE { - STATE_RUNTIME_UNINITIALIZED, - STATE_RUNTIME_RUNNING, - STATE_RUNTIME_ERROR + STATE_RUNTIME_UNINITIALIZED, + STATE_RUNTIME_RUNNING, + STATE_RUNTIME_ERROR }; enum OCRE_CS_EVENT { - // CS Events - EVENT_CS_INITIALIZE, - EVENT_CS_DESTROY, - EVENT_CS_ERROR, - - // Container related events - EVENT_CREATE_CONTAINER, - EVENT_RUN_CONTAINER, - EVENT_STOP_CONTAINER, - EVENT_DESTROY_CONTAINER, - EVENT_RESTART_CONTAINER, - EVENT_ERROR + // CS Events + EVENT_CS_INITIALIZE, + EVENT_CS_DESTROY, + EVENT_CS_ERROR, + + // Container related events + EVENT_CREATE_CONTAINER, + EVENT_RUN_CONTAINER, + EVENT_STOP_CONTAINER, + EVENT_DESTROY_CONTAINER, + EVENT_RESTART_CONTAINER, + EVENT_ERROR }; void start_ocre_cs_thread(ocre_cs_ctx *ctx); diff --git a/src/ocre/components/container_supervisor/cs_sm_impl.c b/src/ocre/components/container_supervisor/cs_sm_impl.c index c462c975..229cb33a 100644 --- a/src/ocre/components/container_supervisor/cs_sm_impl.c +++ b/src/ocre/components/container_supervisor/cs_sm_impl.c @@ -17,10 +17,11 @@ #include "ocre_messaging/ocre_messaging.h" #endif #if defined(CONFIG_OCRE_TIMER) || defined(CONFIG_OCRE_GPIO) || defined(CONFIG_OCRE_SENSORS) || \ - defined(CONFIG_OCRE_CONTAINER_MESSAGING) + defined(CONFIG_OCRE_CONTAINER_MESSAGING) #include "api/ocre_common.h" #endif + #ifdef CONFIG_OCRE_SHELL #include "ocre/shell/ocre_shell.h" #endif @@ -37,10 +38,11 @@ LOG_MODULE_DECLARE(ocre_cs_component, OCRE_LOG_LEVEL); // WAMR heap buffer - uses PSRAM when available #if defined(CONFIG_MEMC) -PSRAM_SECTION_ATTR + PSRAM_SECTION_ATTR #endif static char wamr_heap_buf[CONFIG_OCRE_WAMR_HEAP_BUFFER_SIZE] = {0}; + // Thread pool for container execution #define CONTAINER_THREAD_POOL_SIZE 4 static core_thread_t container_threads[CONTAINER_THREAD_POOL_SIZE]; @@ -50,24 +52,23 @@ static core_mutex_t container_mutex; // Arguments for container threads struct container_thread_args { - ocre_container_t *container; + ocre_container_t *container; }; #ifdef CONFIG_OCRE_MEMORY_CHECK_ENABLED -static size_t ocre_get_available_memory(void) -{ +static size_t ocre_get_available_memory(void) { #ifdef CONFIG_HEAP_MEM_POOL_SIZE - struct k_heap_stats stats; - k_heap_sys_get_stats(&stats); - return stats.free_bytes; + struct k_heap_stats stats; + k_heap_sys_get_stats(&stats); + return stats.free_bytes; #else - extern char *z_malloc_mem_pool_area_start; - extern char *z_malloc_mem_pool_area_end; - extern struct sys_mem_pool_base z_malloc_mem_pool; + extern char *z_malloc_mem_pool_area_start; + extern char *z_malloc_mem_pool_area_end; + extern struct sys_mem_pool_base z_malloc_mem_pool; - size_t total_size = z_malloc_mem_pool_area_end - z_malloc_mem_pool_area_start; - size_t used_size = sys_mem_pool_get_used_size(&z_malloc_mem_pool); - return total_size - used_size; + size_t total_size = z_malloc_mem_pool_area_end - z_malloc_mem_pool_area_start; + size_t used_size = sys_mem_pool_get_used_size(&z_malloc_mem_pool); + return total_size - used_size; #endif } #endif @@ -80,562 +81,556 @@ uint8 preallocated_buf[CONFIG_OCRE_SHARED_HEAP_BUF_SIZE]; #endif #endif -static bool validate_container_memory(ocre_container_t *container) -{ +static bool validate_container_memory(ocre_container_t *container) { #ifdef CONFIG_OCRE_MEMORY_CHECK_ENABLED - size_t requested_heap = container->ocre_container_data.heap_size; - size_t requested_stack = container->ocre_container_data.stack_size; - - if (requested_heap == 0 || requested_heap > CONFIG_OCRE_CONTAINER_DEFAULT_HEAP_SIZE) { - LOG_ERR("Invalid heap size requested: %zu bytes", requested_heap); - return false; - } - - if (requested_stack == 0 || requested_stack > CONFIG_OCRE_CONTAINER_DEFAULT_STACK_SIZE) { - LOG_ERR("Invalid stack size requested: %zu bytes", requested_stack); - return false; - } - - size_t available_memory = ocre_get_available_memory(); - size_t required_memory = requested_heap + requested_stack + sizeof(WASMExecEnv); - - if (available_memory < required_memory) { - LOG_ERR("Insufficient memory for container %d: required %zu bytes, available %zu bytes", - container->container_ID, required_memory, available_memory); - return false; - } - LOG_INF("Memory check passed: %zu bytes required, %zu bytes available", required_memory, available_memory); - - container->ocre_runtime_arguments.stack_size = requested_stack; - container->ocre_runtime_arguments.heap_size = requested_heap; + size_t requested_heap = container->ocre_container_data.heap_size; + size_t requested_stack = container->ocre_container_data.stack_size; + + if (requested_heap == 0 || requested_heap > CONFIG_OCRE_CONTAINER_DEFAULT_HEAP_SIZE) { + LOG_ERR("Invalid heap size requested: %zu bytes", requested_heap); + return false; + } + + if (requested_stack == 0 || requested_stack > CONFIG_OCRE_CONTAINER_DEFAULT_STACK_SIZE) { + LOG_ERR("Invalid stack size requested: %zu bytes", requested_stack); + return false; + } + + size_t available_memory = ocre_get_available_memory(); + size_t required_memory = requested_heap + requested_stack + sizeof(WASMExecEnv); + + if (available_memory < required_memory) { + LOG_ERR("Insufficient memory for container %d: required %zu bytes, available %zu bytes", + container->container_ID, required_memory, available_memory); + return false; + } + LOG_INF("Memory check passed: %zu bytes required, %zu bytes available", required_memory, available_memory); + + container->ocre_runtime_arguments.stack_size = requested_stack; + container->ocre_runtime_arguments.heap_size = requested_heap; #else - container->ocre_runtime_arguments.stack_size = CONFIG_OCRE_CONTAINER_DEFAULT_STACK_SIZE; - container->ocre_runtime_arguments.heap_size = CONFIG_OCRE_CONTAINER_DEFAULT_HEAP_SIZE; + container->ocre_runtime_arguments.stack_size = CONFIG_OCRE_CONTAINER_DEFAULT_STACK_SIZE; + container->ocre_runtime_arguments.heap_size = CONFIG_OCRE_CONTAINER_DEFAULT_HEAP_SIZE; #endif - return true; + return true; } // Container thread entry function -static void container_thread_entry(void *args) -{ - struct container_thread_args *container_args = args; - ocre_container_t *container = container_args->container; - wasm_module_inst_t module_inst = container->ocre_runtime_arguments.module_inst; +static void container_thread_entry(void *args) { + struct container_thread_args *container_args = args; + ocre_container_t *container = container_args->container; + wasm_module_inst_t module_inst = container->ocre_runtime_arguments.module_inst; - // Initialize WASM runtime thread environment - wasm_runtime_init_thread_env(); + // Initialize WASM runtime thread environment + wasm_runtime_init_thread_env(); - LOG_INF("Container thread %d started", container->container_ID); + LOG_INF("Container thread %d started", container->container_ID); #if defined(CONFIG_OCRE_TIMER) || defined(CONFIG_OCRE_GPIO) || defined(CONFIG_OCRE_SENSORS) || \ - defined(CONFIG_OCRE_CONTAINER_MESSAGING) - // Set TLS for the container's WASM module - current_module_tls = &module_inst; -#endif - - // Run the WASM main function with exception handling - bool success = false; - const char *exception = NULL; - - // Clear any previous exceptions - wasm_runtime_clear_exception(module_inst); - - // Execute main function - success = wasm_application_execute_main(module_inst, 0, NULL); - - // Check for exceptions - exception = wasm_runtime_get_exception(module_inst); - if (exception) { - LOG_ERR("Container %d exception: %s", container->container_ID, exception); - success = false; - } - // Update container status - if (container->container_runtime_status != CONTAINER_STATUS_STOPPED) - container->container_runtime_status = success ? CONTAINER_STATUS_STOPPED : CONTAINER_STATUS_ERROR; - // Cleanup sequence - core_mutex_lock(&container->lock); - { - // Cleanup subsystems + defined(CONFIG_OCRE_CONTAINER_MESSAGING) + // Set TLS for the container's WASM module + current_module_tls = &module_inst; +#endif + + // Run the WASM main function with exception handling + bool success = false; + const char *exception = NULL; + + // Clear any previous exceptions + wasm_runtime_clear_exception(module_inst); + + // Execute main function + success = wasm_application_execute_main(module_inst, 0, NULL); + + // Check for exceptions + exception = wasm_runtime_get_exception(module_inst); + if (exception) { + LOG_ERR("Container %d exception: %s", container->container_ID, exception); + success = false; + } + // Update container status + if (container->container_runtime_status != CONTAINER_STATUS_STOPPED) + container->container_runtime_status = success ? CONTAINER_STATUS_STOPPED : CONTAINER_STATUS_ERROR; + // Cleanup sequence + core_mutex_lock(&container->lock); + { + // Cleanup subsystems #ifdef CONFIG_OCRE_TIMER - ocre_timer_cleanup_container(module_inst); + ocre_timer_cleanup_container(module_inst); #endif #ifdef CONFIG_OCRE_GPIO - ocre_gpio_cleanup_container(module_inst); + ocre_gpio_cleanup_container(module_inst); #endif #ifdef CONFIG_OCRE_CONTAINER_MESSAGING - ocre_messaging_cleanup_container(module_inst); + ocre_messaging_cleanup_container(module_inst); #endif - // Clear thread tracking - container_thread_active[container->container_ID] = false; + // Clear thread tracking + container_thread_active[container->container_ID] = false; #if defined(CONFIG_OCRE_TIMER) || defined(CONFIG_OCRE_GPIO) || defined(CONFIG_OCRE_SENSORS) || \ - defined(CONFIG_OCRE_CONTAINER_MESSAGING) - // Clear TLS - current_module_tls = NULL; + defined(CONFIG_OCRE_CONTAINER_MESSAGING) + // Clear TLS + current_module_tls = NULL; #endif - } - core_mutex_unlock(&container->lock); - - if (success) { - LOG_INF("Container %d completed successfully", container->container_ID); - } else { - LOG_ERR("Container %d failed: %s", container->container_ID, exception ? exception : "unknown error"); - } - - // Clean up WASM runtime thread environment - wasm_runtime_destroy_thread_env(); - core_free(args); // Free the dynamically allocated args + + } + core_mutex_unlock(&container->lock); + + if (success) { + LOG_INF("Container %d completed successfully", container->container_ID); + } else { + LOG_ERR("Container %d failed: %s", container->container_ID, + exception ? exception : "unknown error"); + } + + // Clean up WASM runtime thread environment + wasm_runtime_destroy_thread_env(); + core_free(args); // Free the dynamically allocated args } -static int get_available_thread(void) -{ - for (int i = 0; i < CONTAINER_THREAD_POOL_SIZE; i++) { - if (!container_thread_active[i]) { - return i; - } - } - return -1; +static int get_available_thread(void) { + for (int i = 0; i < CONTAINER_THREAD_POOL_SIZE; i++) { + if (!container_thread_active[i]) { + return i; + } + } + return -1; } static int load_binary_to_buffer_fs(ocre_runtime_arguments_t *container_arguments, - ocre_container_data_t *container_data) -{ - int ret = 0; - size_t file_size = 0; - void *file_handle = NULL; - char filepath[FILE_PATH_MAX]; - - ret = core_construct_filepath(filepath, sizeof(filepath), container_data->sha256); - if (ret < 0) { - LOG_ERR("Failed to construct filepath for %s: %d", container_data->sha256, ret); - return ret; - } - ret = core_filestat(filepath, &file_size); - if (ret < 0) { - LOG_ERR("Failed to get file status for %s: %d", filepath, ret); - return ret; - } - - container_arguments->size = file_size; - container_arguments->buffer = storage_heap_alloc(file_size); - if (!container_arguments->buffer) { - LOG_ERR("Failed to allocate memory for container binary from PSRAM."); - return -ENOMEM; - } - - LOG_INF("File path: %s, size: %lu", filepath, (long unsigned int)file_size); - - ret = core_fileopen(filepath, &file_handle); - if (ret < 0) { - LOG_ERR("Failed to open file %s: %d", filepath, ret); - storage_heap_free(container_arguments->buffer); - return ret; - } - - ret = core_fileread(file_handle, container_arguments->buffer, file_size); - if (ret < 0) { - LOG_ERR("Failed to read file %s: %d", filepath, ret); - core_fileclose(file_handle); - storage_heap_free(container_arguments->buffer); - return ret; - } - - ret = core_fileclose(file_handle); - if (ret < 0) { - LOG_ERR("Failed to close file %s: %d", filepath, ret); - storage_heap_free(container_arguments->buffer); - return ret; - } - return 0; + ocre_container_data_t *container_data) { + int ret = 0; + size_t file_size = 0; + void *file_handle = NULL; + char filepath[FILE_PATH_MAX]; + + + ret = core_construct_filepath(filepath, sizeof(filepath), container_data->sha256); + if (ret < 0) { + LOG_ERR("Failed to construct filepath for %s: %d", container_data->sha256, ret); + return ret; + } + ret = core_filestat(filepath, &file_size); + if (ret < 0) { + LOG_ERR("Failed to get file status for %s: %d", filepath, ret); + return ret; + } + + container_arguments->size = file_size; + container_arguments->buffer = storage_heap_alloc(file_size); + if (!container_arguments->buffer) { + LOG_ERR("Failed to allocate memory for container binary from PSRAM."); + return -ENOMEM; + } + + LOG_INF("File path: %s, size: %lu", filepath, (long unsigned int)file_size); + + ret = core_fileopen(filepath, &file_handle); + if (ret < 0) { + LOG_ERR("Failed to open file %s: %d", filepath, ret); + storage_heap_free(container_arguments->buffer); + return ret; + } + + ret = core_fileread(file_handle, container_arguments->buffer, file_size); + if (ret < 0) { + LOG_ERR("Failed to read file %s: %d", filepath, ret); + core_fileclose(file_handle); + storage_heap_free(container_arguments->buffer); + return ret; + } + + ret = core_fileclose(file_handle); + if (ret < 0) { + LOG_ERR("Failed to close file %s: %d", filepath, ret); + storage_heap_free(container_arguments->buffer); + return ret; + } + return 0; } -int CS_ctx_init(ocre_cs_ctx *ctx) -{ - for (int i = 0; i < CONFIG_MAX_CONTAINERS; i++) { - core_mutex_init(&ctx->containers[i].lock); - ctx->containers[i].container_runtime_status = CONTAINER_STATUS_UNKNOWN; - ctx->containers[i].ocre_container_data.heap_size = CONFIG_OCRE_CONTAINER_DEFAULT_HEAP_SIZE; - ctx->containers[i].ocre_container_data.stack_size = CONFIG_OCRE_CONTAINER_DEFAULT_STACK_SIZE; - memset(ctx->containers[i].ocre_container_data.name, 0, - sizeof(ctx->containers[i].ocre_container_data.name)); - memset(ctx->containers[i].ocre_container_data.sha256, 0, - sizeof(ctx->containers[i].ocre_container_data.sha256)); - ctx->containers[i].ocre_container_data.timers = 0; - ctx->containers[i].container_ID = i; - } +int CS_ctx_init(ocre_cs_ctx *ctx) { + for (int i = 0; i < CONFIG_MAX_CONTAINERS; i++) { + core_mutex_init(&ctx->containers[i].lock); + ctx->containers[i].container_runtime_status = CONTAINER_STATUS_UNKNOWN; + ctx->containers[i].ocre_container_data.heap_size = CONFIG_OCRE_CONTAINER_DEFAULT_HEAP_SIZE; + ctx->containers[i].ocre_container_data.stack_size = CONFIG_OCRE_CONTAINER_DEFAULT_STACK_SIZE; + memset(ctx->containers[i].ocre_container_data.name, 0, sizeof(ctx->containers[i].ocre_container_data.name)); + memset(ctx->containers[i].ocre_container_data.sha256, 0, sizeof(ctx->containers[i].ocre_container_data.sha256)); + ctx->containers[i].ocre_container_data.timers = 0; + ctx->containers[i].container_ID = i; + } #ifdef CONFIG_OCRE_SHELL - register_ocre_shell(ctx); + register_ocre_shell(ctx); #endif - core_mutex_init(&container_mutex); - return 0; + core_mutex_init(&container_mutex); + return 0; } -ocre_container_runtime_status_t CS_runtime_init(ocre_cs_ctx *ctx, ocre_container_init_arguments_t *args) -{ - RuntimeInitArgs init_args; - memset(&init_args, 0, sizeof(RuntimeInitArgs)); - init_args.mem_alloc_type = Alloc_With_Pool; - init_args.mem_alloc_option.pool.heap_buf = wamr_heap_buf; - init_args.mem_alloc_option.pool.heap_size = sizeof(wamr_heap_buf); - init_args.native_module_name = "env"; - init_args.n_native_symbols = ocre_api_table_size; - init_args.native_symbols = ocre_api_table; - - if (!wasm_runtime_full_init(&init_args)) { - LOG_ERR("Failed to initialize the WASM runtime"); - return RUNTIME_STATUS_ERROR; - } - - bh_log_set_verbose_level(BH_LOG_LEVEL_WARNING); - - if (!wasm_runtime_register_natives("env", ocre_api_table, ocre_api_table_size)) { - LOG_ERR("Failed to register the API's"); - return RUNTIME_STATUS_ERROR; - } +ocre_container_runtime_status_t CS_runtime_init(ocre_cs_ctx *ctx, ocre_container_init_arguments_t *args) { + RuntimeInitArgs init_args; + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = wamr_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(wamr_heap_buf); + init_args.native_module_name = "env"; + init_args.n_native_symbols = ocre_api_table_size; + init_args.native_symbols = ocre_api_table; + + if (!wasm_runtime_full_init(&init_args)) { + LOG_ERR("Failed to initialize the WASM runtime"); + return RUNTIME_STATUS_ERROR; + } + + bh_log_set_verbose_level(BH_LOG_LEVEL_WARNING); + + if (!wasm_runtime_register_natives("env", ocre_api_table, ocre_api_table_size)) { + LOG_ERR("Failed to register the API's"); + return RUNTIME_STATUS_ERROR; + } #ifdef CONFIG_OCRE_TIMER - ocre_timer_init(); + ocre_timer_init(); #endif #ifdef CONFIG_OCRE_CONTAINER_MESSAGING - ocre_messaging_init(); + ocre_messaging_init(); #endif #ifdef CONFIG_OCRE_SHARED_HEAP - SharedHeapInitArgs heap_init_args; - memset(&heap_init_args, 0, sizeof(heap_init_args)); - + SharedHeapInitArgs heap_init_args; + memset(&heap_init_args, 0, sizeof(heap_init_args)); + #ifdef CONFIG_OCRE_SHARED_HEAP_BUF_PHYSICAL - // Physical mode - map hardware register address - heap_init_args.pre_allocated_addr = (void *)CONFIG_OCRE_SHARED_HEAP_BUF_ADDRESS; - LOG_INF("Creating physical memory mapping at 0x%08X (hardware registers)", CONFIG_OCRE_SHARED_HEAP_BUF_ADDRESS); + // Physical mode - map hardware register address + heap_init_args.pre_allocated_addr = (void *)CONFIG_OCRE_SHARED_HEAP_BUF_ADDRESS; + LOG_INF("Creating physical memory mapping at 0x%08X (hardware registers)", + CONFIG_OCRE_SHARED_HEAP_BUF_ADDRESS); #elif CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL - // Virtual mode - allocate from RAM - heap_init_args.pre_allocated_addr = preallocated_buf; - LOG_INF("Creating virtual shared heap in RAM, size=%d bytes", CONFIG_OCRE_SHARED_HEAP_BUF_SIZE); + // Virtual mode - allocate from RAM + heap_init_args.pre_allocated_addr = preallocated_buf; + LOG_INF("Creating virtual shared heap in RAM, size=%d bytes", + CONFIG_OCRE_SHARED_HEAP_BUF_SIZE); #endif - heap_init_args.size = CONFIG_OCRE_SHARED_HEAP_BUF_SIZE; - _shared_heap = wasm_runtime_create_shared_heap(&heap_init_args); + heap_init_args.size = CONFIG_OCRE_SHARED_HEAP_BUF_SIZE; + _shared_heap = wasm_runtime_create_shared_heap(&heap_init_args); - if (!_shared_heap) { - LOG_ERR("Create preallocated shared heap failed"); - return RUNTIME_STATUS_ERROR; - } + if (!_shared_heap) { + LOG_ERR("Create preallocated shared heap failed"); + return RUNTIME_STATUS_ERROR; + } #endif - storage_heap_init(); - return RUNTIME_STATUS_INITIALIZED; + storage_heap_init(); + return RUNTIME_STATUS_INITIALIZED; } -ocre_container_runtime_status_t CS_runtime_destroy(void) -{ - // Signal event threads to exit gracefully +ocre_container_runtime_status_t CS_runtime_destroy(void) { + // Signal event threads to exit gracefully #if defined(CONFIG_OCRE_TIMER) || defined(CONFIG_OCRE_GPIO) || defined(CONFIG_OCRE_SENSORS) || \ - defined(CONFIG_OCRE_CONTAINER_MESSAGING) - ocre_common_shutdown(); -#endif - - // Abort any active container threads - for (int i = 0; i < CONTAINER_THREAD_POOL_SIZE; i++) { - if (container_thread_active[i]) { - core_thread_destroy(&container_threads[i]); - container_thread_active[i] = false; - } - } - return RUNTIME_STATUS_DESTROYED; + defined(CONFIG_OCRE_CONTAINER_MESSAGING) + ocre_common_shutdown(); +#endif + + // Abort any active container threads + for (int i = 0; i < CONTAINER_THREAD_POOL_SIZE; i++) { + if (container_thread_active[i]) { + core_thread_destroy(&container_threads[i]); + container_thread_active[i] = false; + } + } + return RUNTIME_STATUS_DESTROYED; } -ocre_container_status_t CS_create_container(ocre_container_t *container) -{ - uint32_t curr_container_ID = container->container_ID; - ocre_container_data_t *curr_container_data = &container->ocre_container_data; - ocre_runtime_arguments_t *curr_container_arguments = &container->ocre_runtime_arguments; - - if (container->container_runtime_status == CONTAINER_STATUS_STOPPED) { - LOG_WRN("Container %d is in STOPPED state, destroying it before reuse", curr_container_ID); - CS_destroy_container(container, NULL); - } - - if (container->container_runtime_status != CONTAINER_STATUS_UNKNOWN && - container->container_runtime_status != CONTAINER_STATUS_DESTROYED) { - LOG_ERR("Cannot create container again container with ID: %d, already exists", curr_container_ID); - return CONTAINER_STATUS_ERROR; - } - - if (!validate_container_memory(container)) { - LOG_ERR("Memory check not passed"); - return CONTAINER_STATUS_ERROR; - } - - LOG_INF("Allocating memory for container %d", curr_container_ID); - int ret = load_binary_to_buffer_fs(curr_container_arguments, curr_container_data); - if (ret < 0) { - LOG_ERR("Failed to load binary to buffer: %d", ret); - return CONTAINER_STATUS_ERROR; - } - LOG_INF("Loaded binary to buffer for container %d", curr_container_ID); - - curr_container_arguments->module = - wasm_runtime_load(curr_container_arguments->buffer, curr_container_arguments->size, - curr_container_arguments->error_buf, sizeof(curr_container_arguments->error_buf)); - if (!curr_container_arguments->module) { - LOG_ERR("Failed to load WASM module: %s", curr_container_arguments->error_buf); - storage_heap_free(curr_container_arguments->buffer); - return CONTAINER_STATUS_ERROR; - } - - container->container_runtime_status = CONTAINER_STATUS_CREATED; - LOG_WRN("Created container:%d", curr_container_ID); - return container->container_runtime_status; +ocre_container_status_t CS_create_container(ocre_container_t *container) { + uint32_t curr_container_ID = container->container_ID; + ocre_container_data_t *curr_container_data = &container->ocre_container_data; + ocre_runtime_arguments_t *curr_container_arguments = &container->ocre_runtime_arguments; + + if (container->container_runtime_status == CONTAINER_STATUS_STOPPED) { + LOG_WRN("Container %d is in STOPPED state, destroying it before reuse", curr_container_ID); + CS_destroy_container(container, NULL); + } + + if (container->container_runtime_status != CONTAINER_STATUS_UNKNOWN && + container->container_runtime_status != CONTAINER_STATUS_DESTROYED) { + LOG_ERR("Cannot create container again container with ID: %d, already exists", curr_container_ID); + return CONTAINER_STATUS_ERROR; + } + + if (!validate_container_memory(container)) { + LOG_ERR("Memory check not passed"); + return CONTAINER_STATUS_ERROR; + } + + LOG_INF("Allocating memory for container %d", curr_container_ID); + int ret = load_binary_to_buffer_fs(curr_container_arguments, curr_container_data); + if (ret < 0) { + LOG_ERR("Failed to load binary to buffer: %d", ret); + return CONTAINER_STATUS_ERROR; + } + LOG_INF("Loaded binary to buffer for container %d", curr_container_ID); + + curr_container_arguments->module = + wasm_runtime_load(curr_container_arguments->buffer, curr_container_arguments->size, + curr_container_arguments->error_buf, sizeof(curr_container_arguments->error_buf)); + if (!curr_container_arguments->module) { + LOG_ERR("Failed to load WASM module: %s", curr_container_arguments->error_buf); + storage_heap_free(curr_container_arguments->buffer); + return CONTAINER_STATUS_ERROR; + } + + container->container_runtime_status = CONTAINER_STATUS_CREATED; + LOG_WRN("Created container:%d", curr_container_ID); + return container->container_runtime_status; } -ocre_container_status_t CS_run_container(ocre_container_t *container) -{ - uint32_t curr_container_ID = container->container_ID; - ocre_runtime_arguments_t *curr_container_arguments = &container->ocre_runtime_arguments; - - if (container->container_runtime_status == CONTAINER_STATUS_RUNNING) { - LOG_WRN("Container status is already in RUNNING state"); - return CONTAINER_STATUS_RUNNING; - } - - if (container->container_runtime_status != CONTAINER_STATUS_CREATED && - container->container_runtime_status != CONTAINER_STATUS_STOPPED) { - LOG_ERR("Container (ID: %d), is not in a valid state to run", curr_container_ID); - container->container_runtime_status = CONTAINER_STATUS_ERROR; - return CONTAINER_STATUS_ERROR; - } - -#ifdef CONFIG_OCRE_NETWORKING -#define ADDRESS_POOL_SIZE 1 - const char *addr_pool[ADDRESS_POOL_SIZE] = { - "0.0.0.0/0", - }; - wasm_runtime_set_wasi_addr_pool(curr_container_arguments->module, addr_pool, ADDRESS_POOL_SIZE); - /** - * Configure which domain names a WebAssembly module is allowed to resolve via DNS lookups - * ns_lookup_pool: An array of domain name patterns (e.g., "example.com", "*.example.com", or "*" for any - * domain) - */ - - const char *ns_lookup_pool[] = {"*"}; - wasm_runtime_set_wasi_ns_lookup_pool(curr_container_arguments->module, ns_lookup_pool, - sizeof(ns_lookup_pool) / sizeof(ns_lookup_pool[0])); -#endif - -#ifdef CONFIG_OCRE_CONTAINER_FILESYSTEM -// Simple for now: map CONTAINER_FS_PATH to / -// TODO: eventually every container should probably have its own root folder, -// however wasm_runtime_set_wasi_args expects constant values. -#define DIR_LIST_SIZE 1 - static const char *dir_map_list[DIR_LIST_SIZE] = {"/::" CONTAINER_FS_PATH}; - wasm_runtime_set_wasi_args(curr_container_arguments->module, NULL, 0, dir_map_list, DIR_LIST_SIZE, NULL, 0, - NULL, 0); -#endif - - if (curr_container_arguments->module_inst) { - LOG_INF("WASM runtime already instantiated for container:%d", curr_container_ID); - } else { - LOG_INF("Instantiating WASM runtime for container:%d", curr_container_ID); - curr_container_arguments->module_inst = wasm_runtime_instantiate( - curr_container_arguments->module, curr_container_arguments->stack_size, - curr_container_arguments->heap_size, curr_container_arguments->error_buf, - sizeof(curr_container_arguments->error_buf)); - if (!curr_container_arguments->module_inst) { - LOG_ERR("Failed to instantiate WASM module: %s, for containerID= %d", - curr_container_arguments->error_buf, curr_container_ID); - wasm_runtime_unload(curr_container_arguments->module); - storage_heap_free(curr_container_arguments->buffer); - return CONTAINER_STATUS_ERROR; - } +ocre_container_status_t CS_run_container(ocre_container_t *container) { + uint32_t curr_container_ID = container->container_ID; + ocre_runtime_arguments_t *curr_container_arguments = &container->ocre_runtime_arguments; + + if (container->container_runtime_status == CONTAINER_STATUS_RUNNING) { + LOG_WRN("Container status is already in RUNNING state"); + return CONTAINER_STATUS_RUNNING; + } + + if (container->container_runtime_status != CONTAINER_STATUS_CREATED && + container->container_runtime_status != CONTAINER_STATUS_STOPPED) { + LOG_ERR("Container (ID: %d), is not in a valid state to run", curr_container_ID); + container->container_runtime_status = CONTAINER_STATUS_ERROR; + return CONTAINER_STATUS_ERROR; + } + + #ifdef CONFIG_OCRE_NETWORKING + #define ADDRESS_POOL_SIZE 1 + const char *addr_pool[ADDRESS_POOL_SIZE] = { + "0.0.0.0/0", + }; + wasm_runtime_set_wasi_addr_pool(curr_container_arguments->module, addr_pool, ADDRESS_POOL_SIZE); + /** + * Configure which domain names a WebAssembly module is allowed to resolve via DNS lookups + * ns_lookup_pool: An array of domain name patterns (e.g., "example.com", "*.example.com", or "*" for any domain) + */ + + const char *ns_lookup_pool[] = { + "*" + }; + wasm_runtime_set_wasi_ns_lookup_pool(curr_container_arguments->module, ns_lookup_pool, sizeof(ns_lookup_pool) / sizeof(ns_lookup_pool[0])); + #endif + + #ifdef CONFIG_OCRE_CONTAINER_FILESYSTEM + // Simple for now: map CONTAINER_FS_PATH to / + // TODO: eventually every container should probably have its own root folder, + // however wasm_runtime_set_wasi_args expects constant values. + #define DIR_LIST_SIZE 1 + static const char *dir_map_list[DIR_LIST_SIZE] = { + "/::" CONTAINER_FS_PATH + }; + wasm_runtime_set_wasi_args(curr_container_arguments->module, + NULL, 0, + dir_map_list, DIR_LIST_SIZE, + NULL, 0, NULL, 0); + #endif + + if (curr_container_arguments->module_inst) { + LOG_INF("WASM runtime already instantiated for container:%d", curr_container_ID); + } else { + LOG_INF("Instantiating WASM runtime for container:%d", curr_container_ID); + curr_container_arguments->module_inst = + wasm_runtime_instantiate(curr_container_arguments->module, curr_container_arguments->stack_size, + curr_container_arguments->heap_size, curr_container_arguments->error_buf, + sizeof(curr_container_arguments->error_buf)); + if (!curr_container_arguments->module_inst) { + LOG_ERR("Failed to instantiate WASM module: %s, for containerID= %d", curr_container_arguments->error_buf, + curr_container_ID); + wasm_runtime_unload(curr_container_arguments->module); + storage_heap_free(curr_container_arguments->buffer); + return CONTAINER_STATUS_ERROR; + } #if defined(CONFIG_OCRE_TIMER) || defined(CONFIG_OCRE_GPIO) || defined(CONFIG_OCRE_SENSORS) || \ - defined(CONFIG_OCRE_CONTAINER_MESSAGING) - ocre_register_module(curr_container_arguments->module_inst); + defined(CONFIG_OCRE_CONTAINER_MESSAGING) + ocre_register_module(curr_container_arguments->module_inst); #endif #ifdef CONFIG_OCRE_SHARED_HEAP - LOG_INF("Attaching shared heap to container %d", curr_container_ID); - /* attach module instance to the shared heap */ - if (!wasm_runtime_attach_shared_heap(curr_container_arguments->module_inst, _shared_heap)) { - LOG_ERR("Attach shared heap failed."); - return CONTAINER_STATUS_ERROR; - } + LOG_INF("Attaching shared heap to container %d", curr_container_ID); + /* attach module instance to the shared heap */ + if (!wasm_runtime_attach_shared_heap(curr_container_arguments->module_inst, _shared_heap)) { + LOG_ERR("Attach shared heap failed."); + return CONTAINER_STATUS_ERROR; + } #ifdef CONFIG_OCRE_SHARED_HEAP_BUF_PHYSICAL - // For physical mode, get the base address from the shared heap itself - // The WASM address space already knows about the physical mapping - uint32 shared_heap_base_addr = wasm_runtime_addr_native_to_app( - curr_container_arguments->module_inst, (void *)CONFIG_OCRE_SHARED_HEAP_BUF_ADDRESS); - LOG_INF("Physical shared heap base address in app: 0x%x", shared_heap_base_addr); + // For physical mode, get the base address from the shared heap itself + // The WASM address space already knows about the physical mapping + uint32 shared_heap_base_addr = wasm_runtime_addr_native_to_app( + curr_container_arguments->module_inst, + (void*)CONFIG_OCRE_SHARED_HEAP_BUF_ADDRESS); + LOG_INF("Physical shared heap base address in app: 0x%x", shared_heap_base_addr); #elif CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL - // For virtual mode, convert the allocated buffer address - uint32 shared_heap_base_addr = - wasm_runtime_addr_native_to_app(curr_container_arguments->module_inst, preallocated_buf); - LOG_INF("Virtual shared heap base address in app: 0x%x", shared_heap_base_addr); -#endif - - if (shared_heap_base_addr == 0) { - LOG_ERR("Failed to get shared heap WASM address!"); - return CONTAINER_STATUS_ERROR; - } -#endif - } - core_mutex_lock(&container_mutex); - int thread_idx = get_available_thread(); - if (thread_idx == -1) { - LOG_ERR("No available threads for container %d", curr_container_ID); - container->container_runtime_status = CONTAINER_STATUS_ERROR; - core_mutex_unlock(&container_mutex); - return CONTAINER_STATUS_ERROR; - } - - // Allocate thread arguments dynamically - struct container_thread_args *args = core_malloc(sizeof(struct container_thread_args)); - if (!args) { - LOG_ERR("Failed to allocate thread args for container %d", curr_container_ID); - container->container_runtime_status = CONTAINER_STATUS_ERROR; - core_mutex_unlock(&container_mutex); - return CONTAINER_STATUS_ERROR; - } - args->container = container; - - // Create and start a new thread for the container - char thread_name[16]; - snprintf(thread_name, sizeof(thread_name), "container_%d", curr_container_ID); - container_threads[thread_idx].user_options = curr_container_ID; - int ret = core_thread_create(&container_threads[thread_idx], container_thread_entry, args, thread_name, - CONTAINER_THREAD_STACK_SIZE, 5); - - if (ret != 0) { - LOG_ERR("Failed to create thread for container %d", curr_container_ID); - container->container_runtime_status = CONTAINER_STATUS_ERROR; - - core_free(args); // Free the dynamically allocated args - - core_mutex_unlock(&container_mutex); - return CONTAINER_STATUS_ERROR; - } - - container_thread_active[thread_idx] = true; - core_mutex_unlock(&container_mutex); - - container->container_runtime_status = CONTAINER_STATUS_RUNNING; - LOG_WRN("Running container:%d in dedicated thread", curr_container_ID); - return CONTAINER_STATUS_RUNNING; + // For virtual mode, convert the allocated buffer address + uint32 shared_heap_base_addr = wasm_runtime_addr_native_to_app( + curr_container_arguments->module_inst, + preallocated_buf); + LOG_INF("Virtual shared heap base address in app: 0x%x", shared_heap_base_addr); +#endif + + if (shared_heap_base_addr == 0) { + LOG_ERR("Failed to get shared heap WASM address!"); + return CONTAINER_STATUS_ERROR; + } +#endif + } + core_mutex_lock(&container_mutex); + int thread_idx = get_available_thread(); + if (thread_idx == -1) { + LOG_ERR("No available threads for container %d", curr_container_ID); + container->container_runtime_status = CONTAINER_STATUS_ERROR; + core_mutex_unlock(&container_mutex); + return CONTAINER_STATUS_ERROR; + } + + // Allocate thread arguments dynamically + struct container_thread_args *args = core_malloc(sizeof(struct container_thread_args)); + if (!args) { + LOG_ERR("Failed to allocate thread args for container %d", curr_container_ID); + container->container_runtime_status = CONTAINER_STATUS_ERROR; + core_mutex_unlock(&container_mutex); + return CONTAINER_STATUS_ERROR; + } + args->container = container; + + // Create and start a new thread for the container + char thread_name[16]; + snprintf(thread_name, sizeof(thread_name), "container_%d", curr_container_ID); + container_threads[thread_idx].user_options = curr_container_ID; + int ret = core_thread_create(&container_threads[thread_idx], container_thread_entry, args, thread_name, + CONTAINER_THREAD_STACK_SIZE, 5); + + if (ret != 0) { + LOG_ERR("Failed to create thread for container %d", curr_container_ID); + container->container_runtime_status = CONTAINER_STATUS_ERROR; + + core_free(args); // Free the dynamically allocated args + + core_mutex_unlock(&container_mutex); + return CONTAINER_STATUS_ERROR; + } + + container_thread_active[thread_idx] = true; + core_mutex_unlock(&container_mutex); + + container->container_runtime_status = CONTAINER_STATUS_RUNNING; + LOG_WRN("Running container:%d in dedicated thread", curr_container_ID); + return CONTAINER_STATUS_RUNNING; } -ocre_container_status_t CS_get_container_status(ocre_cs_ctx *ctx, int container_id) -{ - if (container_id < 0 || container_id >= CONFIG_MAX_CONTAINERS) { - LOG_ERR("Invalid container ID: %d", container_id); - return CONTAINER_STATUS_ERROR; - } +ocre_container_status_t CS_get_container_status(ocre_cs_ctx *ctx, int container_id) { + if (container_id < 0 || container_id >= CONFIG_MAX_CONTAINERS) { + LOG_ERR("Invalid container ID: %d", container_id); + return CONTAINER_STATUS_ERROR; + } - return ctx->containers[container_id].container_runtime_status; + return ctx->containers[container_id].container_runtime_status; } -ocre_container_status_t CS_stop_container(ocre_container_t *container, ocre_container_runtime_cb callback) -{ - uint32_t curr_container_ID = container->container_ID; - ocre_runtime_arguments_t *curr_container_arguments = &container->ocre_runtime_arguments; - if (container->container_runtime_status == CONTAINER_STATUS_STOPPED) { - LOG_WRN("Container status is already in STOP state"); - return CONTAINER_STATUS_STOPPED; - } - core_mutex_lock(&container->lock); - { - LOG_INF("Stopping container %d from state %d", curr_container_ID, container->container_runtime_status); - - for (int i = 0; i < CONTAINER_THREAD_POOL_SIZE; i++) { - if (container_thread_active[i] && container_threads[i].user_options == curr_container_ID) { +ocre_container_status_t CS_stop_container(ocre_container_t *container, ocre_container_runtime_cb callback) { + uint32_t curr_container_ID = container->container_ID; + ocre_runtime_arguments_t *curr_container_arguments = &container->ocre_runtime_arguments; + if (container->container_runtime_status == CONTAINER_STATUS_STOPPED) { + LOG_WRN("Container status is already in STOP state"); + return CONTAINER_STATUS_STOPPED; + } + core_mutex_lock(&container->lock); + { + LOG_INF("Stopping container %d from state %d", curr_container_ID, container->container_runtime_status); + + for (int i = 0; i < CONTAINER_THREAD_POOL_SIZE; i++) { + if (container_thread_active[i] && container_threads[i].user_options == curr_container_ID) { #if defined(CONFIG_OCRE_CONTAINER_WAMR_TERMINATION) - /** - * wasm_runtime_terminate uses POSIX signals to terminate the thread from the outside; - * calling core_thread_destroy would try to destroy again the thread, and pthread_join() - * will never return, while freeing the stack would cause segfault. This separation is - * needed to distinguish platform supported by wamr with this features, from those which - * aren't. Since this function exists on those platforms, but stubbed, config parameter - * is used. - */ - wasm_runtime_terminate(curr_container_arguments->module_inst); +/** + * wasm_runtime_terminate uses POSIX signals to terminate the thread from the outside; calling core_thread_destroy + * would try to destroy again the thread, and pthread_join() will never return, while freeing the stack would cause + * segfault. This separation is needed to distinguish platform supported by wamr with this features, + * from those which aren't. Since this function exists on those platforms, but stubbed, config parameter is used. + */ + wasm_runtime_terminate(curr_container_arguments->module_inst); #else - core_thread_destroy(&container_threads[i]); + core_thread_destroy(&container_threads[i]); #endif - container_thread_active[i] = false; - } - } + container_thread_active[i] = false; + } + } #ifdef CONFIG_OCRE_TIMER - ocre_timer_cleanup_container(curr_container_arguments->module_inst); + ocre_timer_cleanup_container(curr_container_arguments->module_inst); #endif #ifdef CONFIG_OCRE_GPIO - ocre_gpio_cleanup_container(curr_container_arguments->module_inst); + ocre_gpio_cleanup_container(curr_container_arguments->module_inst); #endif #ifdef CONFIG_OCRE_CONTAINER_MESSAGING - ocre_messaging_cleanup_container(curr_container_arguments->module_inst); + ocre_messaging_cleanup_container(curr_container_arguments->module_inst); #endif #if defined(CONFIG_OCRE_TIMER) || defined(CONFIG_OCRE_GPIO) || defined(CONFIG_OCRE_SENSORS) || \ - defined(CONFIG_OCRE_CONTAINER_MESSAGING) - ocre_unregister_module(curr_container_arguments->module_inst); + defined(CONFIG_OCRE_CONTAINER_MESSAGING) + ocre_unregister_module(curr_container_arguments->module_inst); #endif - if (curr_container_arguments->module_inst) { - wasm_runtime_deinstantiate(curr_container_arguments->module_inst); - curr_container_arguments->module_inst = NULL; - } + if (curr_container_arguments->module_inst) { + wasm_runtime_deinstantiate(curr_container_arguments->module_inst); + curr_container_arguments->module_inst = NULL; + } - container->container_runtime_status = CONTAINER_STATUS_STOPPED; - } - core_mutex_unlock(&container->lock); + container->container_runtime_status = CONTAINER_STATUS_STOPPED; + } + core_mutex_unlock(&container->lock); - if (callback) { - callback(); - } - return CONTAINER_STATUS_STOPPED; + if (callback) { + callback(); + } + return CONTAINER_STATUS_STOPPED; } -ocre_container_status_t CS_destroy_container(ocre_container_t *container, ocre_container_runtime_cb callback) -{ - if (container->container_runtime_status != CONTAINER_STATUS_STOPPED) { - CS_stop_container(container, NULL); - } - - core_mutex_lock(&container->lock); - { - LOG_INF("Destroying container %d", container->container_ID); - if (container->ocre_runtime_arguments.module) { - wasm_runtime_unload(container->ocre_runtime_arguments.module); - container->ocre_runtime_arguments.module = NULL; - } - - if (container->ocre_runtime_arguments.buffer) { - storage_heap_free(container->ocre_runtime_arguments.buffer); - container->ocre_runtime_arguments.buffer = NULL; - } - - memset(&container->ocre_container_data, 0, sizeof(ocre_container_data_t)); - container->container_runtime_status = CONTAINER_STATUS_DESTROYED; - } - core_mutex_unlock(&container->lock); - - if (callback) { - callback(); - } - return CONTAINER_STATUS_DESTROYED; +ocre_container_status_t CS_destroy_container(ocre_container_t *container, ocre_container_runtime_cb callback) { + if (container->container_runtime_status != CONTAINER_STATUS_STOPPED) { + CS_stop_container(container, NULL); + } + + core_mutex_lock(&container->lock); + { + LOG_INF("Destroying container %d", container->container_ID); + if (container->ocre_runtime_arguments.module) { + wasm_runtime_unload(container->ocre_runtime_arguments.module); + container->ocre_runtime_arguments.module = NULL; + } + + if (container->ocre_runtime_arguments.buffer) { + storage_heap_free(container->ocre_runtime_arguments.buffer); + container->ocre_runtime_arguments.buffer = NULL; + } + + memset(&container->ocre_container_data, 0, sizeof(ocre_container_data_t)); + container->container_runtime_status = CONTAINER_STATUS_DESTROYED; + } + core_mutex_unlock(&container->lock); + + if (callback) { + callback(); + } + return CONTAINER_STATUS_DESTROYED; } -ocre_container_status_t CS_restart_container(ocre_container_t *container, ocre_container_runtime_cb callback) -{ - ocre_container_status_t status = CS_stop_container(container, NULL); - if (status != CONTAINER_STATUS_STOPPED) { - LOG_ERR("Failed to stop container: %d", container->container_ID); - return CONTAINER_STATUS_ERROR; - } - - status = CS_run_container(container); - if (status != CONTAINER_STATUS_RUNNING) { - LOG_ERR("Failed to start container: %d", container->container_ID); - return CONTAINER_STATUS_ERROR; - } - if (callback) { - callback(); - } - - return CONTAINER_STATUS_RUNNING; +ocre_container_status_t CS_restart_container(ocre_container_t *container, ocre_container_runtime_cb callback) { + ocre_container_status_t status = CS_stop_container(container, NULL); + if (status != CONTAINER_STATUS_STOPPED) { + LOG_ERR("Failed to stop container: %d", container->container_ID); + return CONTAINER_STATUS_ERROR; + } + + status = CS_run_container(container); + if (status != CONTAINER_STATUS_RUNNING) { + LOG_ERR("Failed to start container: %d", container->container_ID); + return CONTAINER_STATUS_ERROR; + } + if (callback) { + callback(); + } + + return CONTAINER_STATUS_RUNNING; } diff --git a/src/ocre/components/container_supervisor/message_types.h b/src/ocre/components/container_supervisor/message_types.h index 9c29425c..8a7f1e75 100644 --- a/src/ocre/components/container_supervisor/message_types.h +++ b/src/ocre/components/container_supervisor/message_types.h @@ -11,23 +11,23 @@ #include "ocre_core_external.h" struct install { - char name[OCRE_MODULE_NAME_LEN]; // download_count = 0; - - start_ocre_cs_thread(ctx); - core_sleep_ms(1000); - return RUNTIME_STATUS_INITIALIZED; +ocre_container_runtime_status_t ocre_container_runtime_init(ocre_cs_ctx *ctx, ocre_container_init_arguments_t *args) { + // Zeroing the context + if (CS_runtime_init(ctx, args) != RUNTIME_STATUS_INITIALIZED) { + LOG_ERR("Failed to initialize container runtime"); + return RUNTIME_STATUS_ERROR; + } + + CS_ctx_init(ctx); + ctx->download_count = 0; + + start_ocre_cs_thread(ctx); + core_sleep_ms(1000); + return RUNTIME_STATUS_INITIALIZED; } -ocre_container_status_t ocre_container_runtime_destroy(void) -{ - wasm_runtime_destroy(); - destroy_ocre_cs_thread(); - return RUNTIME_STATUS_DESTROYED; +ocre_container_status_t ocre_container_runtime_destroy(void) { + wasm_runtime_destroy(); + destroy_ocre_cs_thread(); + return RUNTIME_STATUS_DESTROYED; } ocre_container_status_t ocre_container_runtime_create_container(ocre_cs_ctx *ctx, ocre_container_data_t *container_data, - int *container_id, ocre_container_runtime_cb callback) -{ - int i; - uint8_t validity_flag = false; - // Find available slot for new container - for (i = 0; i < CONFIG_MAX_CONTAINERS; i++) { - if ((ctx->containers[i].container_runtime_status == CONTAINER_STATUS_UNKNOWN) || - (ctx->containers[i].container_runtime_status == CONTAINER_STATUS_DESTROYED)) { - *container_id = i; - ctx->containers[i].container_ID = i; - validity_flag = true; - break; - } - } - - if (validity_flag == false) { - LOG_ERR("No available slots, unable to create container"); - return CONTAINER_STATUS_ERROR; - } - LOG_INF("Request to create new container in slot: %d", *container_id); - - struct ocre_message event = {.event = EVENT_CREATE_CONTAINER}; - ocre_container_data_t Data; - event.containerId = *container_id; - Data = *container_data; - ctx->containers[*container_id].ocre_container_data = Data; - ctx->containers[*container_id].ocre_runtime_arguments.module_inst = NULL; - ctx->download_count++; - - ocre_component_send(&ocre_cs_component, &event); - return CONTAINER_STATUS_CREATED; + int *container_id, ocre_container_runtime_cb callback) { + int i; + uint8_t validity_flag = false; + // Find available slot for new container + for (i = 0; i < CONFIG_MAX_CONTAINERS; i++) { + if ((ctx->containers[i].container_runtime_status == CONTAINER_STATUS_UNKNOWN) || + (ctx->containers[i].container_runtime_status == CONTAINER_STATUS_DESTROYED)) { + *container_id = i; + ctx->containers[i].container_ID = i; + validity_flag = true; + break; + } + } + + if (validity_flag == false) { + LOG_ERR("No available slots, unable to create container"); + return CONTAINER_STATUS_ERROR; + } + LOG_INF("Request to create new container in slot: %d", *container_id); + + struct ocre_message event = {.event = EVENT_CREATE_CONTAINER}; + ocre_container_data_t Data; + event.containerId = *container_id; + Data = *container_data; + ctx->containers[*container_id].ocre_container_data = Data; + ctx->containers[*container_id].ocre_runtime_arguments.module_inst = NULL; + ctx->download_count++; + + ocre_component_send(&ocre_cs_component, &event); + return CONTAINER_STATUS_CREATED; } -ocre_container_status_t ocre_container_runtime_run_container(int container_id, ocre_container_runtime_cb callback) -{ - if (container_id < 0 || container_id >= CONFIG_MAX_CONTAINERS) { - LOG_ERR("Invalid container ID: %d", container_id); - return CONTAINER_STATUS_ERROR; - } - - LOG_INF("Request to run container in slot:%d", container_id); - struct ocre_message event = {.event = EVENT_RUN_CONTAINER}; - event.containerId = container_id; - ocre_component_send(&ocre_cs_component, &event); - return CONTAINER_STATUS_RUNNING; +ocre_container_status_t ocre_container_runtime_run_container(int container_id, ocre_container_runtime_cb callback) { + if (container_id < 0 || container_id >= CONFIG_MAX_CONTAINERS) { + LOG_ERR("Invalid container ID: %d", container_id); + return CONTAINER_STATUS_ERROR; + } + + LOG_INF("Request to run container in slot:%d", container_id); + struct ocre_message event = {.event = EVENT_RUN_CONTAINER}; + event.containerId = container_id; + ocre_component_send(&ocre_cs_component, &event); + return CONTAINER_STATUS_RUNNING; } -ocre_container_status_t ocre_container_runtime_get_container_status(ocre_cs_ctx *ctx, int container_id) -{ - if (container_id < 0 || container_id >= CONFIG_MAX_CONTAINERS) { - LOG_ERR("Invalid container ID: %d", container_id); - return CONTAINER_STATUS_ERROR; - } +ocre_container_status_t ocre_container_runtime_get_container_status(ocre_cs_ctx *ctx, int container_id) { + if (container_id < 0 || container_id >= CONFIG_MAX_CONTAINERS) { + LOG_ERR("Invalid container ID: %d", container_id); + return CONTAINER_STATUS_ERROR; + } - return ctx->containers[container_id].container_runtime_status; + return ctx->containers[container_id].container_runtime_status; } -ocre_container_status_t ocre_container_runtime_stop_container(int container_id, ocre_container_runtime_cb callback) -{ - if (container_id < 0 || container_id >= CONFIG_MAX_CONTAINERS) { - LOG_ERR("Invalid container ID: %d", container_id); - return CONTAINER_STATUS_ERROR; - } - LOG_INF("Request to stop container in slot: %d", container_id); - struct ocre_message event = {.event = EVENT_STOP_CONTAINER}; - event.containerId = container_id; - ocre_component_send(&ocre_cs_component, &event); - return CONTAINER_STATUS_STOPPED; +ocre_container_status_t ocre_container_runtime_stop_container(int container_id, ocre_container_runtime_cb callback) { + if (container_id < 0 || container_id >= CONFIG_MAX_CONTAINERS) { + LOG_ERR("Invalid container ID: %d", container_id); + return CONTAINER_STATUS_ERROR; + } + LOG_INF("Request to stop container in slot: %d", container_id); + struct ocre_message event = {.event = EVENT_STOP_CONTAINER}; + event.containerId = container_id; + ocre_component_send(&ocre_cs_component, &event); + return CONTAINER_STATUS_STOPPED; } ocre_container_status_t ocre_container_runtime_destroy_container(ocre_cs_ctx *ctx, int container_id, - ocre_container_runtime_cb callback) -{ - if (container_id < 0 || container_id >= CONFIG_MAX_CONTAINERS) { - LOG_ERR("Invalid container ID: %d", container_id); - return CONTAINER_STATUS_ERROR; - } - LOG_INF("Request to destroy container in slot: %d", container_id); - struct ocre_message event = {.event = EVENT_DESTROY_CONTAINER}; - event.containerId = container_id; - ocre_component_send(&ocre_cs_component, &event); - return CONTAINER_STATUS_DESTROYED; + ocre_container_runtime_cb callback) { + if (container_id < 0 || container_id >= CONFIG_MAX_CONTAINERS) { + LOG_ERR("Invalid container ID: %d", container_id); + return CONTAINER_STATUS_ERROR; + } + LOG_INF("Request to destroy container in slot: %d", container_id); + struct ocre_message event = {.event = EVENT_DESTROY_CONTAINER}; + event.containerId = container_id; + ocre_component_send(&ocre_cs_component, &event); + return CONTAINER_STATUS_DESTROYED; } ocre_container_status_t ocre_container_runtime_restart_container(ocre_cs_ctx *ctx, int container_id, - ocre_container_runtime_cb callback) -{ - if (container_id < 0 || container_id >= CONFIG_MAX_CONTAINERS) { - LOG_ERR("Invalid container ID: %d", container_id); - return CONTAINER_STATUS_ERROR; - } - LOG_INF("Request to restart container in slot: %d", container_id); - struct ocre_message event = {.event = EVENT_RESTART_CONTAINER}; - event.containerId = container_id; - ocre_component_send(&ocre_cs_component, &event); - return ctx->containers[container_id].container_runtime_status; + ocre_container_runtime_cb callback) { + if (container_id < 0 || container_id >= CONFIG_MAX_CONTAINERS) { + LOG_ERR("Invalid container ID: %d", container_id); + return CONTAINER_STATUS_ERROR; + } + LOG_INF("Request to restart container in slot: %d", container_id); + struct ocre_message event = {.event = EVENT_RESTART_CONTAINER}; + event.containerId = container_id; + ocre_component_send(&ocre_cs_component, &event); + return ctx->containers[container_id].container_runtime_status; } diff --git a/src/ocre/ocre_container_runtime/ocre_container_runtime.h b/src/ocre/ocre_container_runtime/ocre_container_runtime.h index e3dda8ff..2d1b46cd 100644 --- a/src/ocre/ocre_container_runtime/ocre_container_runtime.h +++ b/src/ocre/ocre_container_runtime/ocre_container_runtime.h @@ -13,22 +13,23 @@ #include "ocre_core_external.h" #include "wasm_export.h" -#define OCRE_CR_DEBUG_ON 0 // Debug flag for container runtime (0: OFF, 1: ON) -#define FILE_PATH_MAX 256 // Maximum file path length +#define OCRE_CR_DEBUG_ON 0 // Debug flag for container runtime (0: OFF, 1: ON) +#define FILE_PATH_MAX 256 // Maximum file path length #define OCRE_CR_INIT_TIMEOUT 500 // Timeout to wait for the container registry to initialize + /** * @brief Structure containing the runtime arguments for a container runtime. */ typedef struct ocre_runtime_arguments_t { - uint32_t size; ///< Size of the buffer. - char *buffer; ///< Pointer to the buffer containing the WASM module. - char error_buf[128]; ///< Buffer to store error messages. - wasm_module_t module; ///< Handle to the loaded WASM module. - wasm_module_inst_t module_inst; ///< Handle to the instantiated WASM module. - wasm_function_inst_t func; ///< Handle to the function to be executed within the WASM module. - uint32_t stack_size; ///< Stack size for the WASM module. - uint32_t heap_size; ///< Heap size for the WASM module. + uint32_t size; ///< Size of the buffer. + char *buffer; ///< Pointer to the buffer containing the WASM module. + char error_buf[128]; ///< Buffer to store error messages. + wasm_module_t module; ///< Handle to the loaded WASM module. + wasm_module_inst_t module_inst; ///< Handle to the instantiated WASM module. + wasm_function_inst_t func; ///< Handle to the function to be executed within the WASM module. + uint32_t stack_size; ///< Stack size for the WASM module. + uint32_t heap_size; ///< Heap size for the WASM module. } ocre_runtime_arguments_t; /** @@ -36,62 +37,62 @@ typedef struct ocre_runtime_arguments_t { * NOT USED YET */ typedef enum { - OCRE_CONTAINER_PERM_READ_ONLY, ///< Container has read-only permissions. - OCRE_CONTAINER_PERM_READ_WRITE, ///< Container has read and write permissions. - OCRE_CONTAINER_PERM_EXECUTE ///< Container has execute permissions. + OCRE_CONTAINER_PERM_READ_ONLY, ///< Container has read-only permissions. + OCRE_CONTAINER_PERM_READ_WRITE, ///< Container has read and write permissions. + OCRE_CONTAINER_PERM_EXECUTE ///< Container has execute permissions. } ocre_container_permissions_t; /** * @brief Enum representing the possible status of the container runtime */ typedef enum { - RUNTIME_STATUS_UNKNOWN, ///< Status is unknown. - RUNTIME_STATUS_INITIALIZED, ///< Runtime has been initialized. - RUNTIME_STATUS_DESTROYED, ///< Runtime has been destroyed - RUNTIME_STATUS_ERROR ///< An error occurred with the container. + RUNTIME_STATUS_UNKNOWN, ///< Status is unknown. + RUNTIME_STATUS_INITIALIZED, ///< Runtime has been initialized. + RUNTIME_STATUS_DESTROYED, ///< Runtime has been destroyed + RUNTIME_STATUS_ERROR ///< An error occurred with the container. } ocre_container_runtime_status_t; /** * @brief Enum representing the possible status of a container. */ typedef enum { - CONTAINER_STATUS_UNKNOWN, ///< Status is unknown. - CONTAINER_STATUS_CREATED, ///< Container has been created. - CONTAINER_STATUS_RUNNING, ///< Container is currently running. - CONTAINER_STATUS_STOPPED, ///< Container has been stopped. - CONTAINER_STATUS_DESTROYED, ///< Container has been destroyed. - CONTAINER_STATUS_UNRESPONSIVE, ///< Container is unresponsive. -> For Healthcheck - CONTAINER_STATUS_ERROR, ///< An error occurred with the container. + CONTAINER_STATUS_UNKNOWN, ///< Status is unknown. + CONTAINER_STATUS_CREATED, ///< Container has been created. + CONTAINER_STATUS_RUNNING, ///< Container is currently running. + CONTAINER_STATUS_STOPPED, ///< Container has been stopped. + CONTAINER_STATUS_DESTROYED, ///< Container has been destroyed. + CONTAINER_STATUS_UNRESPONSIVE, ///< Container is unresponsive. -> For Healthcheck + CONTAINER_STATUS_ERROR, ///< An error occurred with the container. } ocre_container_status_t; typedef struct ocre_container_runtime_init_arguments_t { - uint32_t default_stack_size; ///< Stack size for the WASM module. - uint32_t default_heap_size; ///< Heap size for the WASM module. - int maximum_containers; ///< Maximum number of containers allowed. - NativeSymbol *ocre_api_functions; + uint32_t default_stack_size; ///< Stack size for the WASM module. + uint32_t default_heap_size; ///< Heap size for the WASM module. + int maximum_containers; ///< Maximum number of containers allowed. + NativeSymbol *ocre_api_functions; } ocre_container_init_arguments_t; /** * @brief Structure representing the data associated with a container. */ typedef struct ocre_container_data_t { - char name[OCRE_MODULE_NAME_LEN]; // pin >= CONFIG_OCRE_GPIO_PINS_PER_PORT || - config->port_idx >= CONFIG_OCRE_GPIO_MAX_PORTS || !port_ready[config->port_idx]) { - LOG_ERR("Invalid GPIO config: port=%d, pin=%d, port_ready=%d", config ? config->port_idx : -1, - config ? config->pin : -1, config ? port_ready[config->port_idx] : false); - return -EINVAL; - } - int port_idx = config->port_idx; - gpio_pin_t pin = config->pin; - gpio_flags_t flags = (config->direction == OCRE_GPIO_DIR_INPUT) ? GPIO_INPUT : GPIO_OUTPUT; - if (config->direction == OCRE_GPIO_DIR_INPUT) { - flags |= GPIO_PULL_UP; - } - int ret = gpio_pin_configure(gpio_ports[port_idx], pin, flags); - if (ret != 0) { - LOG_ERR("Failed to configure GPIO pin %d on port %d: %d", pin, port_idx, ret); - return ret; - } - wasm_module_inst_t module_inst = ocre_get_current_module(); - if (!module_inst) { - LOG_ERR("No current module instance for GPIO configuration"); - return -EINVAL; - } - int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; - if (global_pin >= CONFIG_OCRE_GPIO_MAX_PINS) { - LOG_ERR("Global pin %d exceeds max %d", global_pin, CONFIG_OCRE_GPIO_MAX_PINS); - return -EINVAL; - } - gpio_pins[global_pin] = (gpio_pin_ocre){.in_use = 1, - .direction = (config->direction == OCRE_GPIO_DIR_OUTPUT), - .pin_number = pin, - .port_idx = port_idx, - .cb = NULL, - .owner = module_inst}; - ocre_increment_resource_count(module_inst, OCRE_RESOURCE_TYPE_GPIO); - LOG_INF("Configured GPIO pin %d on port %d (global %d) for module %p", pin, port_idx, global_pin, - (void *)module_inst); - return 0; +int ocre_gpio_configure(const ocre_gpio_config_t *config) { + if (!gpio_system_initialized || !config || config->pin >= CONFIG_OCRE_GPIO_PINS_PER_PORT || + config->port_idx >= CONFIG_OCRE_GPIO_MAX_PORTS || !port_ready[config->port_idx]) { + LOG_ERR("Invalid GPIO config: port=%d, pin=%d, port_ready=%d", config ? config->port_idx : -1, + config ? config->pin : -1, config ? port_ready[config->port_idx] : false); + return -EINVAL; + } + int port_idx = config->port_idx; + gpio_pin_t pin = config->pin; + gpio_flags_t flags = (config->direction == OCRE_GPIO_DIR_INPUT) ? GPIO_INPUT : GPIO_OUTPUT; + if (config->direction == OCRE_GPIO_DIR_INPUT) { + flags |= GPIO_PULL_UP; + } + int ret = gpio_pin_configure(gpio_ports[port_idx], pin, flags); + if (ret != 0) { + LOG_ERR("Failed to configure GPIO pin %d on port %d: %d", pin, port_idx, ret); + return ret; + } + wasm_module_inst_t module_inst = ocre_get_current_module(); + if (!module_inst) { + LOG_ERR("No current module instance for GPIO configuration"); + return -EINVAL; + } + int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; + if (global_pin >= CONFIG_OCRE_GPIO_MAX_PINS) { + LOG_ERR("Global pin %d exceeds max %d", global_pin, CONFIG_OCRE_GPIO_MAX_PINS); + return -EINVAL; + } + gpio_pins[global_pin] = (gpio_pin_ocre){.in_use = 1, + .direction = (config->direction == OCRE_GPIO_DIR_OUTPUT), + .pin_number = pin, + .port_idx = port_idx, + .cb = NULL, + .owner = module_inst}; + ocre_increment_resource_count(module_inst, OCRE_RESOURCE_TYPE_GPIO); + LOG_INF("Configured GPIO pin %d on port %d (global %d) for module %p", pin, port_idx, global_pin, + (void *)module_inst); + return 0; } -int ocre_gpio_pin_set(int pin, ocre_gpio_pin_state_t state) -{ - if (pin >= CONFIG_OCRE_GPIO_MAX_PINS || !gpio_pins[pin].in_use || gpio_pins[pin].direction != 1 || - !port_ready[gpio_pins[pin].port_idx]) { - LOG_ERR("Invalid GPIO pin %d or not configured as output or port not ready", pin); - return -EINVAL; - } - int ret = gpio_pin_set(gpio_ports[gpio_pins[pin].port_idx], gpio_pins[pin].pin_number, state); - if (ret != 0) { - LOG_ERR("Failed to set GPIO pin %d: %d", pin, ret); - } - return ret; +int ocre_gpio_pin_set(int pin, ocre_gpio_pin_state_t state) { + if (pin >= CONFIG_OCRE_GPIO_MAX_PINS || !gpio_pins[pin].in_use || gpio_pins[pin].direction != 1 || + !port_ready[gpio_pins[pin].port_idx]) { + LOG_ERR("Invalid GPIO pin %d or not configured as output or port not ready", pin); + return -EINVAL; + } + int ret = gpio_pin_set(gpio_ports[gpio_pins[pin].port_idx], gpio_pins[pin].pin_number, state); + if (ret != 0) { + LOG_ERR("Failed to set GPIO pin %d: %d", pin, ret); + } + return ret; } -ocre_gpio_pin_state_t ocre_gpio_pin_get(int pin) -{ - if (pin >= CONFIG_OCRE_GPIO_MAX_PINS || !gpio_pins[pin].in_use || !port_ready[gpio_pins[pin].port_idx]) { - LOG_ERR("Invalid or unconfigured GPIO pin %d or port not ready", pin); - return -EINVAL; - } - int value = gpio_pin_get(gpio_ports[gpio_pins[pin].port_idx], gpio_pins[pin].pin_number); - return (value >= 0) ? (value ? OCRE_GPIO_PIN_SET : OCRE_GPIO_PIN_RESET) : value; +ocre_gpio_pin_state_t ocre_gpio_pin_get(int pin) { + if (pin >= CONFIG_OCRE_GPIO_MAX_PINS || !gpio_pins[pin].in_use || !port_ready[gpio_pins[pin].port_idx]) { + LOG_ERR("Invalid or unconfigured GPIO pin %d or port not ready", pin); + return -EINVAL; + } + int value = gpio_pin_get(gpio_ports[gpio_pins[pin].port_idx], gpio_pins[pin].pin_number); + return (value >= 0) ? (value ? OCRE_GPIO_PIN_SET : OCRE_GPIO_PIN_RESET) : value; } -int ocre_gpio_pin_toggle(int pin) -{ - if (pin >= CONFIG_OCRE_GPIO_MAX_PINS || !gpio_pins[pin].in_use || gpio_pins[pin].direction != 1 || - !port_ready[gpio_pins[pin].port_idx]) { - LOG_ERR("Invalid GPIO pin %d or not configured as output or port not ready", pin); - return -EINVAL; - } - int ret = gpio_pin_toggle(gpio_ports[gpio_pins[pin].port_idx], gpio_pins[pin].pin_number); - if (ret != 0) { - LOG_ERR("Failed to toggle GPIO pin %d: %d", pin, ret); - } - return ret; +int ocre_gpio_pin_toggle(int pin) { + if (pin >= CONFIG_OCRE_GPIO_MAX_PINS || !gpio_pins[pin].in_use || gpio_pins[pin].direction != 1 || + !port_ready[gpio_pins[pin].port_idx]) { + LOG_ERR("Invalid GPIO pin %d or not configured as output or port not ready", pin); + return -EINVAL; + } + int ret = gpio_pin_toggle(gpio_ports[gpio_pins[pin].port_idx], gpio_pins[pin].pin_number); + if (ret != 0) { + LOG_ERR("Failed to toggle GPIO pin %d: %d", pin, ret); + } + return ret; } -int ocre_gpio_register_callback(int pin) -{ - if (pin >= CONFIG_OCRE_GPIO_MAX_PINS || !gpio_pins[pin].in_use || gpio_pins[pin].direction != 0 || - !port_ready[gpio_pins[pin].port_idx]) { - LOG_ERR("Invalid GPIO pin %d or not configured as input or port not ready", pin); - return -EINVAL; - } - gpio_pin_ocre *gpio = &gpio_pins[pin]; - if (!gpio->cb) { - gpio->cb = k_calloc(1, sizeof(struct gpio_callback)); - if (!gpio->cb) { - LOG_ERR("Failed to allocate memory for GPIO callback"); - return -ENOMEM; - } - } - int ret = gpio_pin_interrupt_configure(gpio_ports[gpio->port_idx], gpio->pin_number, GPIO_INT_EDGE_BOTH); - if (ret) { - LOG_ERR("Failed to configure interrupt for GPIO pin %d: %d", pin, ret); - k_free(gpio->cb); - gpio->cb = NULL; - return ret; - } - gpio_init_callback(gpio->cb, gpio_callback_handler, BIT(gpio->pin_number)); - ret = gpio_add_callback(gpio_ports[gpio->port_idx], gpio->cb); - if (ret) { - LOG_ERR("Failed to add callback for GPIO pin %d: %d", pin, ret); - k_free(gpio->cb); - gpio->cb = NULL; - return ret; - } - LOG_INF("Registered callback for GPIO pin %d (port %d, pin %d)", pin, gpio->port_idx, gpio->pin_number); - return 0; +int ocre_gpio_register_callback(int pin) { + if (pin >= CONFIG_OCRE_GPIO_MAX_PINS || !gpio_pins[pin].in_use || gpio_pins[pin].direction != 0 || + !port_ready[gpio_pins[pin].port_idx]) { + LOG_ERR("Invalid GPIO pin %d or not configured as input or port not ready", pin); + return -EINVAL; + } + gpio_pin_ocre *gpio = &gpio_pins[pin]; + if (!gpio->cb) { + gpio->cb = k_calloc(1, sizeof(struct gpio_callback)); + if (!gpio->cb) { + LOG_ERR("Failed to allocate memory for GPIO callback"); + return -ENOMEM; + } + } + int ret = gpio_pin_interrupt_configure(gpio_ports[gpio->port_idx], gpio->pin_number, GPIO_INT_EDGE_BOTH); + if (ret) { + LOG_ERR("Failed to configure interrupt for GPIO pin %d: %d", pin, ret); + k_free(gpio->cb); + gpio->cb = NULL; + return ret; + } + gpio_init_callback(gpio->cb, gpio_callback_handler, BIT(gpio->pin_number)); + ret = gpio_add_callback(gpio_ports[gpio->port_idx], gpio->cb); + if (ret) { + LOG_ERR("Failed to add callback for GPIO pin %d: %d", pin, ret); + k_free(gpio->cb); + gpio->cb = NULL; + return ret; + } + LOG_INF("Registered callback for GPIO pin %d (port %d, pin %d)", pin, gpio->port_idx, gpio->pin_number); + return 0; } -int ocre_gpio_unregister_callback(int pin) -{ - if (pin >= CONFIG_OCRE_GPIO_MAX_PINS || !gpio_pins[pin].in_use || !gpio_pins[pin].cb || - !port_ready[gpio_pins[pin].port_idx]) { - LOG_ERR("Invalid GPIO pin %d or no callback registered or port not ready", pin); - return -EINVAL; - } - gpio_pin_ocre *gpio = &gpio_pins[pin]; - int ret = gpio_pin_interrupt_configure(gpio_ports[gpio->port_idx], gpio->pin_number, GPIO_INT_DISABLE); - if (ret) { - LOG_ERR("Failed to disable interrupt for GPIO pin %d: %d", pin, ret); - return ret; - } - ret = gpio_remove_callback(gpio_ports[gpio->port_idx], gpio->cb); - if (ret) { - LOG_ERR("Failed to remove callback for GPIO pin %d: %d", pin, ret); - } - k_free(gpio->cb); - gpio->cb = NULL; - LOG_INF("Unregistered callback for GPIO pin %d", pin); - return ret; +int ocre_gpio_unregister_callback(int pin) { + if (pin >= CONFIG_OCRE_GPIO_MAX_PINS || !gpio_pins[pin].in_use || !gpio_pins[pin].cb || + !port_ready[gpio_pins[pin].port_idx]) { + LOG_ERR("Invalid GPIO pin %d or no callback registered or port not ready", pin); + return -EINVAL; + } + gpio_pin_ocre *gpio = &gpio_pins[pin]; + int ret = gpio_pin_interrupt_configure(gpio_ports[gpio->port_idx], gpio->pin_number, GPIO_INT_DISABLE); + if (ret) { + LOG_ERR("Failed to disable interrupt for GPIO pin %d: %d", pin, ret); + return ret; + } + ret = gpio_remove_callback(gpio_ports[gpio->port_idx], gpio->cb); + if (ret) { + LOG_ERR("Failed to remove callback for GPIO pin %d: %d", pin, ret); + } + k_free(gpio->cb); + gpio->cb = NULL; + LOG_INF("Unregistered callback for GPIO pin %d", pin); + return ret; } -void ocre_gpio_cleanup_container(wasm_module_inst_t module_inst) -{ - if (!gpio_system_initialized || !module_inst) { - LOG_DBG("GPIO system not initialized or invalid module %p", (void *)module_inst); - return; - } - for (int i = 0; i < CONFIG_OCRE_GPIO_MAX_PINS; i++) { - if (gpio_pins[i].in_use && gpio_pins[i].owner == module_inst) { - if (gpio_pins[i].direction == 0) { - ocre_gpio_unregister_callback(i); - } - gpio_pins[i].in_use = 0; - gpio_pins[i].owner = NULL; - ocre_decrement_resource_count(module_inst, OCRE_RESOURCE_TYPE_GPIO); - LOG_DBG("Cleaned up GPIO pin %d", i); - } - } - LOG_DBG("Cleaned up GPIO resources for module %p", (void *)module_inst); +void ocre_gpio_cleanup_container(wasm_module_inst_t module_inst) { + if (!gpio_system_initialized || !module_inst) { + LOG_DBG("GPIO system not initialized or invalid module %p", (void *)module_inst); + return; + } + for (int i = 0; i < CONFIG_OCRE_GPIO_MAX_PINS; i++) { + if (gpio_pins[i].in_use && gpio_pins[i].owner == module_inst) { + if (gpio_pins[i].direction == 0) { + ocre_gpio_unregister_callback(i); + } + gpio_pins[i].in_use = 0; + gpio_pins[i].owner = NULL; + ocre_decrement_resource_count(module_inst, OCRE_RESOURCE_TYPE_GPIO); + LOG_DBG("Cleaned up GPIO pin %d", i); + } + } + LOG_DBG("Cleaned up GPIO resources for module %p", (void *)module_inst); } -void ocre_gpio_set_dispatcher(wasm_exec_env_t exec_env) -{ - wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); - if (module_inst) { - // Dispatcher set in wasm container application - LOG_INF("Set dispatcher for module %p", (void *)module_inst); - } +void ocre_gpio_set_dispatcher(wasm_exec_env_t exec_env) { + wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); + if (module_inst) { + // Dispatcher set in wasm container application + LOG_INF("Set dispatcher for module %p", (void *)module_inst); + } } -int ocre_gpio_wasm_init(wasm_exec_env_t exec_env) -{ - return ocre_gpio_init(); +int ocre_gpio_wasm_init(wasm_exec_env_t exec_env) { + return ocre_gpio_init(); } -int ocre_gpio_wasm_configure(wasm_exec_env_t exec_env, int port, int pin, int direction) -{ - wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); - if (!module_inst) { - LOG_ERR("No module instance for GPIO configuration"); - return -EINVAL; - } - if (port >= CONFIG_OCRE_GPIO_MAX_PORTS || pin >= CONFIG_OCRE_GPIO_PINS_PER_PORT || !port_ready[port]) { - LOG_ERR("Invalid port=%d, pin=%d, or port not ready", port, pin); - return -EINVAL; - } - int global_pin = port * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; - LOG_INF("Configuring GPIO: port=%d, pin=%d, global_pin=%d, direction=%d", port, pin, global_pin, direction); - if (global_pin >= CONFIG_OCRE_GPIO_MAX_PINS) { - LOG_ERR("Global pin %d exceeds max %d", global_pin, CONFIG_OCRE_GPIO_MAX_PINS); - return -EINVAL; - } - ocre_gpio_config_t config = {.pin = pin, .port_idx = port, .direction = direction}; - return ocre_gpio_configure(&config); +int ocre_gpio_wasm_configure(wasm_exec_env_t exec_env, int port, int pin, int direction) { + wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); + if (!module_inst) { + LOG_ERR("No module instance for GPIO configuration"); + return -EINVAL; + } + if (port >= CONFIG_OCRE_GPIO_MAX_PORTS || pin >= CONFIG_OCRE_GPIO_PINS_PER_PORT || !port_ready[port]) { + LOG_ERR("Invalid port=%d, pin=%d, or port not ready", port, pin); + return -EINVAL; + } + int global_pin = port * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; + LOG_INF("Configuring GPIO: port=%d, pin=%d, global_pin=%d, direction=%d", port, pin, global_pin, direction); + if (global_pin >= CONFIG_OCRE_GPIO_MAX_PINS) { + LOG_ERR("Global pin %d exceeds max %d", global_pin, CONFIG_OCRE_GPIO_MAX_PINS); + return -EINVAL; + } + ocre_gpio_config_t config = {.pin = pin, .port_idx = port, .direction = direction}; + return ocre_gpio_configure(&config); } -int ocre_gpio_wasm_set(wasm_exec_env_t exec_env, int port, int pin, int state) -{ - int global_pin = port * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; - LOG_INF("Setting GPIO: port=%d, pin=%d, global_pin=%d, state=%d", port, pin, global_pin, state); - if (!port_ready[port]) { - LOG_ERR("Port %d not ready", port); - return -EINVAL; - } - return ocre_gpio_pin_set(global_pin, state ? OCRE_GPIO_PIN_SET : OCRE_GPIO_PIN_RESET); +int ocre_gpio_wasm_set(wasm_exec_env_t exec_env, int port, int pin, int state) { + int global_pin = port * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; + LOG_INF("Setting GPIO: port=%d, pin=%d, global_pin=%d, state=%d", port, pin, global_pin, state); + if (!port_ready[port]) { + LOG_ERR("Port %d not ready", port); + return -EINVAL; + } + return ocre_gpio_pin_set(global_pin, state ? OCRE_GPIO_PIN_SET : OCRE_GPIO_PIN_RESET); } -int ocre_gpio_wasm_get(wasm_exec_env_t exec_env, int port, int pin) -{ - int global_pin = port * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; - LOG_INF("Getting GPIO: port=%d, pin=%d, global_pin=%d", port, pin, global_pin); - if (!port_ready[port]) { - LOG_ERR("Port %d not ready", port); - return -EINVAL; - } - return ocre_gpio_pin_get(global_pin); +int ocre_gpio_wasm_get(wasm_exec_env_t exec_env, int port, int pin) { + int global_pin = port * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; + LOG_INF("Getting GPIO: port=%d, pin=%d, global_pin=%d", port, pin, global_pin); + if (!port_ready[port]) { + LOG_ERR("Port %d not ready", port); + return -EINVAL; + } + return ocre_gpio_pin_get(global_pin); } -int ocre_gpio_wasm_toggle(wasm_exec_env_t exec_env, int port, int pin) -{ - int global_pin = port * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; - LOG_INF("Toggling GPIO: port=%d, pin=%d, global_pin=%d", port, pin, global_pin); - if (!port_ready[port]) { - LOG_ERR("Port %d not ready", port); - return -EINVAL; - } - return ocre_gpio_pin_toggle(global_pin); +int ocre_gpio_wasm_toggle(wasm_exec_env_t exec_env, int port, int pin) { + int global_pin = port * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; + LOG_INF("Toggling GPIO: port=%d, pin=%d, global_pin=%d", port, pin, global_pin); + if (!port_ready[port]) { + LOG_ERR("Port %d not ready", port); + return -EINVAL; + } + return ocre_gpio_pin_toggle(global_pin); } -int ocre_gpio_wasm_register_callback(wasm_exec_env_t exec_env, int port, int pin) -{ - int global_pin = port * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; - LOG_INF("Registering callback: port=%d, pin=%d, global_pin=%d", port, pin, global_pin); - if (global_pin >= CONFIG_OCRE_GPIO_MAX_PINS || !port_ready[port]) { - LOG_ERR("Global pin %d exceeds max %d or port %d not ready", global_pin, CONFIG_OCRE_GPIO_MAX_PINS, - port); - return -EINVAL; - } - return ocre_gpio_register_callback(global_pin); +int ocre_gpio_wasm_register_callback(wasm_exec_env_t exec_env, int port, int pin) { + int global_pin = port * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; + LOG_INF("Registering callback: port=%d, pin=%d, global_pin=%d", port, pin, global_pin); + if (global_pin >= CONFIG_OCRE_GPIO_MAX_PINS || !port_ready[port]) { + LOG_ERR("Global pin %d exceeds max %d or port %d not ready", global_pin, CONFIG_OCRE_GPIO_MAX_PINS, port); + return -EINVAL; + } + return ocre_gpio_register_callback(global_pin); } -int ocre_gpio_wasm_unregister_callback(wasm_exec_env_t exec_env, int port, int pin) -{ - int global_pin = port * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; - LOG_INF("Unregistering callback: port=%d, pin=%d, global_pin=%d", port, pin, global_pin); - if (!port_ready[port]) { - LOG_ERR("Port %d not ready", port); - return -EINVAL; - } - return ocre_gpio_unregister_callback(global_pin); +int ocre_gpio_wasm_unregister_callback(wasm_exec_env_t exec_env, int port, int pin) { + int global_pin = port * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; + LOG_INF("Unregistering callback: port=%d, pin=%d, global_pin=%d", port, pin, global_pin); + if (!port_ready[port]) { + LOG_ERR("Port %d not ready", port); + return -EINVAL; + } + return ocre_gpio_unregister_callback(global_pin); } -static void gpio_callback_handler(const struct device *port, struct gpio_callback *cb, gpio_port_pins_t pins) -{ - if (!port || !cb) { - LOG_ERR("Null port or callback in GPIO handler"); - return; - } - for (int i = 0; i < CONFIG_OCRE_GPIO_MAX_PINS; i++) { - if (gpio_pins[i].in_use && gpio_pins[i].cb == cb && (pins & BIT(gpio_pins[i].pin_number))) { - int state = gpio_pin_get(port, gpio_pins[i].pin_number); - if (state >= 0) { - - ocre_event_t event; - event.type = OCRE_RESOURCE_TYPE_GPIO; - event.data.gpio_event.pin_id = gpio_pins[i].pin_number; - event.data.gpio_event.port = gpio_pins[i].port_idx; - event.data.gpio_event.state = (uint32_t)state; - event.owner = gpio_pins[i].owner; - core_spinlock_key_t key = core_spinlock_lock(&ocre_event_queue_lock); - if (core_eventq_put(&ocre_event_queue, &event) != 0) { - LOG_ERR("Failed to queue GPIO event for pin %d", i); - } else { - LOG_INF("Queued GPIO event for pin %d (port=%d, pin=%d), state=%d", i, - gpio_pins[i].port_idx, gpio_pins[i].pin_number, state); - } - core_spinlock_unlock(&ocre_event_queue_lock, key); - } - } - } +static void gpio_callback_handler(const struct device *port, struct gpio_callback *cb, gpio_port_pins_t pins) { + if (!port || !cb) { + LOG_ERR("Null port or callback in GPIO handler"); + return; + } + for (int i = 0; i < CONFIG_OCRE_GPIO_MAX_PINS; i++) { + if (gpio_pins[i].in_use && gpio_pins[i].cb == cb && (pins & BIT(gpio_pins[i].pin_number))) { + int state = gpio_pin_get(port, gpio_pins[i].pin_number); + if (state >= 0) { + + ocre_event_t event; + event.type = OCRE_RESOURCE_TYPE_GPIO; + event.data.gpio_event.pin_id = gpio_pins[i].pin_number; + event.data.gpio_event.port = gpio_pins[i].port_idx; + event.data.gpio_event.state = (uint32_t)state; + event.owner = gpio_pins[i].owner; + core_spinlock_key_t key = core_spinlock_lock(&ocre_event_queue_lock); + if (core_eventq_put(&ocre_event_queue, &event) != 0) { + LOG_ERR("Failed to queue GPIO event for pin %d", i); + } else { + LOG_INF("Queued GPIO event for pin %d (port=%d, pin=%d), state=%d", i, gpio_pins[i].port_idx, + gpio_pins[i].pin_number, state); + } + core_spinlock_unlock(&ocre_event_queue_lock, key); + } + } + } } //======================================================================================================================================================================================================================================================================================================== // By Name //======================================================================================================================================================================================================================================================================================================== -static int find_port_index(const struct device *port) -{ - if (!port) { - LOG_ERR("Null port provided to find_port_index"); - return -EINVAL; - } - for (int i = 0; i < CONFIG_OCRE_GPIO_MAX_PORTS; i++) { - if (port_ready[i] && gpio_ports[i] == port) { - LOG_DBG("Found port at index %d: %p", i, port); - return i; - } - } - LOG_ERR("Port %p not found in initialized ports", port); - return -1; +static int find_port_index(const struct device *port) { + if (!port) { + LOG_ERR("Null port provided to find_port_index"); + return -EINVAL; + } + for (int i = 0; i < CONFIG_OCRE_GPIO_MAX_PORTS; i++) { + if (port_ready[i] && gpio_ports[i] == port) { + LOG_DBG("Found port at index %d: %p", i, port); + return i; + } + } + LOG_ERR("Port %p not found in initialized ports", port); + return -1; } -static int resolve_gpio_alias(const char *name, int *port_idx, gpio_pin_t *pin) -{ - if (!name || !port_idx || !pin) { - LOG_ERR("Invalid parameters: name=%p, port_idx=%p, pin=%p", name, port_idx, pin); - return -EINVAL; - } - - // Check if GPIO system is initialized - if (!gpio_system_initialized) { - LOG_ERR("GPIO system not initialized when resolving alias '%s'", name); - return -ENODEV; - } - - // First check if we already have this alias cached - for (int i = 0; i < gpio_alias_count; i++) { - if (strcmp(gpio_aliases[i].name, name) == 0) { - *port_idx = gpio_aliases[i].port_idx; - *pin = gpio_aliases[i].pin; - LOG_INF("Found cached GPIO alias '%s': port %d, pin %d", name, *port_idx, *pin); - return 0; - } - } - - // Try to resolve the alias using devicetree - const struct gpio_dt_spec *spec = NULL; - static struct gpio_dt_spec gpio_spec; - - // Check common aliases - only compile if they exist - if (strcmp(name, "led0") == 0) { +static int resolve_gpio_alias(const char *name, int *port_idx, gpio_pin_t *pin) { + if (!name || !port_idx || !pin) { + LOG_ERR("Invalid parameters: name=%p, port_idx=%p, pin=%p", name, port_idx, pin); + return -EINVAL; + } + + // Check if GPIO system is initialized + if (!gpio_system_initialized) { + LOG_ERR("GPIO system not initialized when resolving alias '%s'", name); + return -ENODEV; + } + + // First check if we already have this alias cached + for (int i = 0; i < gpio_alias_count; i++) { + if (strcmp(gpio_aliases[i].name, name) == 0) { + *port_idx = gpio_aliases[i].port_idx; + *pin = gpio_aliases[i].pin; + LOG_INF("Found cached GPIO alias '%s': port %d, pin %d", name, *port_idx, *pin); + return 0; + } + } + + // Try to resolve the alias using devicetree + const struct gpio_dt_spec *spec = NULL; + static struct gpio_dt_spec gpio_spec; + + // Check common aliases - only compile if they exist + if (strcmp(name, "led0") == 0) { #if DT_NODE_EXISTS(DT_ALIAS(led0)) - gpio_spec = (struct gpio_dt_spec)GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios); - spec = &gpio_spec; - LOG_DBG("Resolved DT_ALIAS(led0) to port %p, pin %d", spec ? spec->port : NULL, spec ? spec->pin : 0); + gpio_spec = (struct gpio_dt_spec)GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios); + spec = &gpio_spec; + LOG_DBG("Resolved DT_ALIAS(led0) to port %p, pin %d", spec ? spec->port : NULL, spec ? spec->pin : 0); #else - LOG_ERR("DT_ALIAS(led0) not defined in device tree"); - return -ENODEV; + LOG_ERR("DT_ALIAS(led0) not defined in device tree"); + return -ENODEV; #endif - } else if (strcmp(name, "led1") == 0) { + } else if (strcmp(name, "led1") == 0) { #if DT_NODE_EXISTS(DT_ALIAS(led1)) - gpio_spec = (struct gpio_dt_spec)GPIO_DT_SPEC_GET(DT_ALIAS(led1), gpios); - spec = &gpio_spec; - LOG_DBG("Resolved DT_ALIAS(led1) to port %p, pin %d", spec ? spec->port : NULL, spec ? spec->pin : 0); + gpio_spec = (struct gpio_dt_spec)GPIO_DT_SPEC_GET(DT_ALIAS(led1), gpios); + spec = &gpio_spec; + LOG_DBG("Resolved DT_ALIAS(led1) to port %p, pin %d", spec ? spec->port : NULL, spec ? spec->pin : 0); #else - LOG_ERR("DT_ALIAS(led1) not defined in device tree"); - return -ENODEV; + LOG_ERR("DT_ALIAS(led1) not defined in device tree"); + return -ENODEV; #endif - } else if (strcmp(name, "led2") == 0) { + } else if (strcmp(name, "led2") == 0) { #if DT_NODE_EXISTS(DT_ALIAS(led2)) - gpio_spec = (struct gpio_dt_spec)GPIO_DT_SPEC_GET(DT_ALIAS(led2), gpios); - spec = &gpio_spec; - LOG_DBG("Resolved DT_ALIAS(led2) to port %p, pin %d", spec ? spec->port : NULL, spec ? spec->pin : 0); + gpio_spec = (struct gpio_dt_spec)GPIO_DT_SPEC_GET(DT_ALIAS(led2), gpios); + spec = &gpio_spec; + LOG_DBG("Resolved DT_ALIAS(led2) to port %p, pin %d", spec ? spec->port : NULL, spec ? spec->pin : 0); #else - LOG_ERR("DT_ALIAS(led2) not defined in device tree"); - return -ENODEV; + LOG_ERR("DT_ALIAS(led2) not defined in device tree"); + return -ENODEV; #endif - } else if (strcmp(name, "sw0") == 0) { + } else if (strcmp(name, "sw0") == 0) { #if DT_NODE_EXISTS(DT_ALIAS(sw0)) - gpio_spec = (struct gpio_dt_spec)GPIO_DT_SPEC_GET(DT_ALIAS(sw0), gpios); - spec = &gpio_spec; - LOG_DBG("Resolved DT_ALIAS(sw0) to port %p, pin %d", spec ? spec->port : NULL, spec ? spec->pin : 0); + gpio_spec = (struct gpio_dt_spec)GPIO_DT_SPEC_GET(DT_ALIAS(sw0), gpios); + spec = &gpio_spec; + LOG_DBG("Resolved DT_ALIAS(sw0) to port %p, pin %d", spec ? spec->port : NULL, spec ? spec->pin : 0); #else - LOG_ERR("DT_ALIAS(sw0) not defined in device tree"); - return -ENODEV; + LOG_ERR("DT_ALIAS(sw0) not defined in device tree"); + return -ENODEV; #endif - } else if (strcmp(name, "sw1") == 0) { + } else if (strcmp(name, "sw1") == 0) { #if DT_NODE_EXISTS(DT_ALIAS(sw1)) - gpio_spec = (struct gpio_dt_spec)GPIO_DT_SPEC_GET(DT_ALIAS(sw1), gpios); - spec = &gpio_spec; - LOG_DBG("Resolved DT_ALIAS(sw1) to port %p, pin %d", spec ? spec->port : NULL, spec ? spec->pin : 0); + gpio_spec = (struct gpio_dt_spec)GPIO_DT_SPEC_GET(DT_ALIAS(sw1), gpios); + spec = &gpio_spec; + LOG_DBG("Resolved DT_ALIAS(sw1) to port %p, pin %d", spec ? spec->port : NULL, spec ? spec->pin : 0); #else - LOG_ERR("DT_ALIAS(sw1) not defined in device tree"); - return -ENODEV; + LOG_ERR("DT_ALIAS(sw1) not defined in device tree"); + return -ENODEV; #endif - } else { - LOG_ERR("Unknown GPIO alias '%s'", name); - return -EINVAL; - } - - if (!spec || !spec->port) { - LOG_ERR("GPIO alias '%s' not found in device tree or invalid spec", name); - return -ENODEV; - } - - // Verify device readiness - if (!device_is_ready(spec->port)) { - LOG_ERR("Device for GPIO alias '%s' (port %p) not ready", name, spec->port); - return -ENODEV; - } - - // Find the port index - int found_port_idx = find_port_index(spec->port); - if (found_port_idx < 0) { - LOG_ERR("Port for alias '%s' (port %p) not found in initialized ports", name, spec->port); - // Debug: print all available ports - LOG_ERR("Available ports:"); - bool any_ports = false; - for (int i = 0; i < CONFIG_OCRE_GPIO_MAX_PORTS; i++) { - if (port_ready[i] && gpio_ports[i]) { - LOG_ERR(" Port %d: %p", i, gpio_ports[i]); - any_ports = true; - } - } - if (!any_ports) { - LOG_ERR(" No ports initialized"); - } - LOG_ERR("Looking for port: %p", spec->port); - return -ENODEV; - } - - *port_idx = found_port_idx; - *pin = spec->pin; - - // Cache the resolved alias - if (gpio_alias_count < CONFIG_OCRE_GPIO_MAX_PINS) { - gpio_aliases[gpio_alias_count].name = name; - gpio_aliases[gpio_alias_count].port = spec->port; - gpio_aliases[gpio_alias_count].pin = spec->pin; - gpio_aliases[gpio_alias_count].port_idx = found_port_idx; - gpio_alias_count++; - LOG_INF("Cached GPIO alias '%s': port %d, pin %d", name, found_port_idx, spec->pin); - } else { - LOG_WRN("Cannot cache alias '%s': alias table full", name); - } - - LOG_INF("Resolved GPIO alias '%s' to port %d, pin %d", name, *port_idx, *pin); - return 0; + } else { + LOG_ERR("Unknown GPIO alias '%s'", name); + return -EINVAL; + } + + if (!spec || !spec->port) { + LOG_ERR("GPIO alias '%s' not found in device tree or invalid spec", name); + return -ENODEV; + } + + // Verify device readiness + if (!device_is_ready(spec->port)) { + LOG_ERR("Device for GPIO alias '%s' (port %p) not ready", name, spec->port); + return -ENODEV; + } + + // Find the port index + int found_port_idx = find_port_index(spec->port); + if (found_port_idx < 0) { + LOG_ERR("Port for alias '%s' (port %p) not found in initialized ports", name, spec->port); + // Debug: print all available ports + LOG_ERR("Available ports:"); + bool any_ports = false; + for (int i = 0; i < CONFIG_OCRE_GPIO_MAX_PORTS; i++) { + if (port_ready[i] && gpio_ports[i]) { + LOG_ERR(" Port %d: %p", i, gpio_ports[i]); + any_ports = true; + } + } + if (!any_ports) { + LOG_ERR(" No ports initialized"); + } + LOG_ERR("Looking for port: %p", spec->port); + return -ENODEV; + } + + *port_idx = found_port_idx; + *pin = spec->pin; + + // Cache the resolved alias + if (gpio_alias_count < CONFIG_OCRE_GPIO_MAX_PINS) { + gpio_aliases[gpio_alias_count].name = name; + gpio_aliases[gpio_alias_count].port = spec->port; + gpio_aliases[gpio_alias_count].pin = spec->pin; + gpio_aliases[gpio_alias_count].port_idx = found_port_idx; + gpio_alias_count++; + LOG_INF("Cached GPIO alias '%s': port %d, pin %d", name, found_port_idx, spec->pin); + } else { + LOG_WRN("Cannot cache alias '%s': alias table full", name); + } + + LOG_INF("Resolved GPIO alias '%s' to port %d, pin %d", name, *port_idx, *pin); + return 0; } -int ocre_gpio_configure_by_name(const char *name, ocre_gpio_direction_t direction) -{ - if (!name) { - LOG_ERR("Invalid name parameter"); - return -EINVAL; - } - - int port_idx; - gpio_pin_t pin; - int ret = resolve_gpio_alias(name, &port_idx, &pin); - if (ret != 0) { - return ret; - } - - ocre_gpio_config_t config = {.pin = pin, .port_idx = port_idx, .direction = direction}; - - return ocre_gpio_configure(&config); +int ocre_gpio_configure_by_name(const char *name, ocre_gpio_direction_t direction) { + if (!name) { + LOG_ERR("Invalid name parameter"); + return -EINVAL; + } + + int port_idx; + gpio_pin_t pin; + int ret = resolve_gpio_alias(name, &port_idx, &pin); + if (ret != 0) { + return ret; + } + + ocre_gpio_config_t config = { + .pin = pin, + .port_idx = port_idx, + .direction = direction + }; + + return ocre_gpio_configure(&config); } -int ocre_gpio_set_by_name(const char *name, ocre_gpio_pin_state_t state) -{ - if (!name) { - LOG_ERR("Invalid name parameter"); - return -EINVAL; - } - - int port_idx; - gpio_pin_t pin; - int ret = resolve_gpio_alias(name, &port_idx, &pin); - if (ret != 0) { - return ret; - } - - int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; - return ocre_gpio_pin_set(global_pin, state); +int ocre_gpio_set_by_name(const char *name, ocre_gpio_pin_state_t state) { + if (!name) { + LOG_ERR("Invalid name parameter"); + return -EINVAL; + } + + int port_idx; + gpio_pin_t pin; + int ret = resolve_gpio_alias(name, &port_idx, &pin); + if (ret != 0) { + return ret; + } + + int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; + return ocre_gpio_pin_set(global_pin, state); } -int ocre_gpio_toggle_by_name(const char *name) -{ - if (!name) { - LOG_ERR("Invalid name parameter"); - return -EINVAL; - } - - int port_idx; - gpio_pin_t pin; - int ret = resolve_gpio_alias(name, &port_idx, &pin); - if (ret != 0) { - return ret; - } - - int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; - return ocre_gpio_pin_toggle(global_pin); +int ocre_gpio_toggle_by_name(const char *name) { + if (!name) { + LOG_ERR("Invalid name parameter"); + return -EINVAL; + } + + int port_idx; + gpio_pin_t pin; + int ret = resolve_gpio_alias(name, &port_idx, &pin); + if (ret != 0) { + return ret; + } + + int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; + return ocre_gpio_pin_toggle(global_pin); } -ocre_gpio_pin_state_t ocre_gpio_get_by_name(const char *name) -{ - if (!name) { - LOG_ERR("Invalid name parameter"); - return -EINVAL; - } - - int port_idx; - gpio_pin_t pin; - int ret = resolve_gpio_alias(name, &port_idx, &pin); - if (ret != 0) { - return ret; - } - - int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; - return ocre_gpio_pin_get(global_pin); +ocre_gpio_pin_state_t ocre_gpio_get_by_name(const char *name) { + if (!name) { + LOG_ERR("Invalid name parameter"); + return -EINVAL; + } + + int port_idx; + gpio_pin_t pin; + int ret = resolve_gpio_alias(name, &port_idx, &pin); + if (ret != 0) { + return ret; + } + + int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; + return ocre_gpio_pin_get(global_pin); } -int ocre_gpio_wasm_configure_by_name(wasm_exec_env_t exec_env, const char *name, int direction) -{ - if (!name) { - LOG_ERR("Invalid name parameter"); - return -EINVAL; - } - - wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); - if (!module_inst) { - LOG_ERR("No module instance for GPIO configuration"); - return -EINVAL; - } - - LOG_INF("Configuring GPIO by name: %s, direction=%d", name, direction); - return ocre_gpio_configure_by_name(name, direction); +int ocre_gpio_wasm_configure_by_name(wasm_exec_env_t exec_env, const char *name, int direction) { + if (!name) { + LOG_ERR("Invalid name parameter"); + return -EINVAL; + } + + wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); + if (!module_inst) { + LOG_ERR("No module instance for GPIO configuration"); + return -EINVAL; + } + + LOG_INF("Configuring GPIO by name: %s, direction=%d", name, direction); + return ocre_gpio_configure_by_name(name, direction); } -int ocre_gpio_wasm_set_by_name(wasm_exec_env_t exec_env, const char *name, int state) -{ - if (!name) { - LOG_ERR("Invalid name parameter"); - return -EINVAL; - } +int ocre_gpio_wasm_set_by_name(wasm_exec_env_t exec_env, const char *name, int state) { + if (!name) { + LOG_ERR("Invalid name parameter"); + return -EINVAL; + } - LOG_INF("Setting GPIO by name: %s, state=%d", name, state); - return ocre_gpio_set_by_name(name, state ? OCRE_GPIO_PIN_SET : OCRE_GPIO_PIN_RESET); + LOG_INF("Setting GPIO by name: %s, state=%d", name, state); + return ocre_gpio_set_by_name(name, state ? OCRE_GPIO_PIN_SET : OCRE_GPIO_PIN_RESET); } -int ocre_gpio_wasm_get_by_name(wasm_exec_env_t exec_env, const char *name) -{ - if (!name) { - LOG_ERR("Invalid name parameter"); - return -EINVAL; - } +int ocre_gpio_wasm_get_by_name(wasm_exec_env_t exec_env, const char *name) { + if (!name) { + LOG_ERR("Invalid name parameter"); + return -EINVAL; + } - LOG_INF("Getting GPIO by name: %s", name); - return ocre_gpio_get_by_name(name); + LOG_INF("Getting GPIO by name: %s", name); + return ocre_gpio_get_by_name(name); } -int ocre_gpio_wasm_toggle_by_name(wasm_exec_env_t exec_env, const char *name) -{ - if (!name) { - LOG_ERR("Invalid name parameter"); - return -EINVAL; - } +int ocre_gpio_wasm_toggle_by_name(wasm_exec_env_t exec_env, const char *name) { + if (!name) { + LOG_ERR("Invalid name parameter"); + return -EINVAL; + } - LOG_INF("Toggling GPIO by name: %s", name); - return ocre_gpio_toggle_by_name(name); + LOG_INF("Toggling GPIO by name: %s", name); + return ocre_gpio_toggle_by_name(name); } -int ocre_gpio_wasm_register_callback_by_name(wasm_exec_env_t exec_env, const char *name) -{ - if (!name) { - LOG_ERR("Invalid name parameter"); - return -EINVAL; - } - - int port_idx; - gpio_pin_t pin; - int ret = resolve_gpio_alias(name, &port_idx, &pin); - if (ret != 0) { - return ret; - } - - int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; - LOG_INF("Registering callback by name: %s, global_pin=%d", name, global_pin); - - if (global_pin >= CONFIG_OCRE_GPIO_MAX_PINS) { - LOG_ERR("Global pin %d exceeds max %d", global_pin, CONFIG_OCRE_GPIO_MAX_PINS); - return -EINVAL; - } - - return ocre_gpio_register_callback(global_pin); +int ocre_gpio_wasm_register_callback_by_name(wasm_exec_env_t exec_env, const char *name) { + if (!name) { + LOG_ERR("Invalid name parameter"); + return -EINVAL; + } + + int port_idx; + gpio_pin_t pin; + int ret = resolve_gpio_alias(name, &port_idx, &pin); + if (ret != 0) { + return ret; + } + + int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; + LOG_INF("Registering callback by name: %s, global_pin=%d", name, global_pin); + + if (global_pin >= CONFIG_OCRE_GPIO_MAX_PINS) { + LOG_ERR("Global pin %d exceeds max %d", global_pin, CONFIG_OCRE_GPIO_MAX_PINS); + return -EINVAL; + } + + return ocre_gpio_register_callback(global_pin); } -int ocre_gpio_wasm_unregister_callback_by_name(wasm_exec_env_t exec_env, const char *name) -{ - if (!name) { - LOG_ERR("Invalid name parameter"); - return -EINVAL; - } +int ocre_gpio_wasm_unregister_callback_by_name(wasm_exec_env_t exec_env, const char *name) { + if (!name) { + LOG_ERR("Invalid name parameter"); + return -EINVAL; + } - int port_idx; - gpio_pin_t pin; - int ret = resolve_gpio_alias(name, &port_idx, &pin); - if (ret != 0) { - return ret; - } + int port_idx; + gpio_pin_t pin; + int ret = resolve_gpio_alias(name, &port_idx, &pin); + if (ret != 0) { + return ret; + } - int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; - LOG_INF("Unregistering callback by name: %s, global_pin=%d", name, global_pin); + int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; + LOG_INF("Unregistering callback by name: %s, global_pin=%d", name, global_pin); - return ocre_gpio_unregister_callback(global_pin); + return ocre_gpio_unregister_callback(global_pin); } diff --git a/src/ocre/ocre_gpio/ocre_gpio.h b/src/ocre/ocre_gpio/ocre_gpio.h index 74258537..80e48bc0 100644 --- a/src/ocre/ocre_gpio/ocre_gpio.h +++ b/src/ocre/ocre_gpio/ocre_gpio.h @@ -29,25 +29,25 @@ * GPIO pin state */ typedef enum { - OCRE_GPIO_PIN_RESET = 0, - OCRE_GPIO_PIN_SET = 1 + OCRE_GPIO_PIN_RESET = 0, + OCRE_GPIO_PIN_SET = 1 } ocre_gpio_pin_state_t; /** * GPIO pin direction */ typedef enum { - OCRE_GPIO_DIR_INPUT = 0, - OCRE_GPIO_DIR_OUTPUT = 1 + OCRE_GPIO_DIR_INPUT = 0, + OCRE_GPIO_DIR_OUTPUT = 1 } ocre_gpio_direction_t; /** * GPIO configuration structure */ typedef struct { - int pin; /**< GPIO pin number (logical) */ - int port_idx; - ocre_gpio_direction_t direction; /**< Pin direction */ + int pin; /**< GPIO pin number (logical) */ + int port_idx; + ocre_gpio_direction_t direction; /**< Pin direction */ } ocre_gpio_config_t; /** @@ -128,7 +128,7 @@ void ocre_gpio_set_dispatcher(wasm_exec_env_t exec_env); /** * @brief Configure a GPIO pin by alias name - * + * * @param name GPIO alias name (e.g., "led0", "sw0") * @param direction GPIO direction (OCRE_GPIO_DIR_INPUT or OCRE_GPIO_DIR_OUTPUT) * @return int 0 on success, negative error code on failure @@ -137,7 +137,7 @@ int ocre_gpio_configure_by_name(const char *name, ocre_gpio_direction_t directio /** * @brief Set a GPIO pin state by alias name - * + * * @param name GPIO alias name (e.g., "led0", "sw0") * @param state Pin state (OCRE_GPIO_PIN_SET or OCRE_GPIO_PIN_RESET) * @return int 0 on success, negative error code on failure @@ -146,7 +146,7 @@ int ocre_gpio_set_by_name(const char *name, ocre_gpio_pin_state_t state); /** * @brief Toggle a GPIO pin by alias name - * + * * @param name GPIO alias name (e.g., "led0", "sw0") * @return int 0 on success, negative error code on failure */ @@ -154,7 +154,7 @@ int ocre_gpio_toggle_by_name(const char *name); /** * @brief Get a GPIO pin state by alias name - * + * * @param name GPIO alias name (e.g., "led0", "sw0") * @return ocre_gpio_pin_state_t Pin state or negative error code on failure */ diff --git a/src/ocre/ocre_input_file.h b/src/ocre/ocre_input_file.h index 7b8d74ad..fea12761 100644 --- a/src/ocre/ocre_input_file.h +++ b/src/ocre/ocre_input_file.h @@ -9,220 +9,328 @@ #define OCRE_INPUT_FILE_H // Sample WASM binary data static const unsigned char wasm_binary[] = { - 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x35, 0x09, 0x60, 0x03, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, - 0x60, 0x03, 0x7f, 0x7e, 0x7f, 0x01, 0x7e, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, - 0x60, 0x04, 0x7f, 0x7e, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x04, 0x7f, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x01, - 0x7f, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x01, 0x7f, 0x02, 0xb0, 0x01, 0x05, 0x16, 0x77, 0x61, 0x73, 0x69, - 0x5f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x31, - 0x08, 0x66, 0x64, 0x5f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x00, 0x02, 0x16, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x73, - 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x31, 0x0d, 0x66, - 0x64, 0x5f, 0x66, 0x64, 0x73, 0x74, 0x61, 0x74, 0x5f, 0x67, 0x65, 0x74, 0x00, 0x03, 0x16, 0x77, 0x61, 0x73, - 0x69, 0x5f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, - 0x31, 0x07, 0x66, 0x64, 0x5f, 0x73, 0x65, 0x65, 0x6b, 0x00, 0x04, 0x16, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x73, - 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x31, 0x08, 0x66, - 0x64, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x00, 0x05, 0x16, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x73, 0x6e, 0x61, - 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x31, 0x09, 0x70, 0x72, 0x6f, - 0x63, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x00, 0x06, 0x03, 0x1d, 0x1c, 0x07, 0x07, 0x08, 0x02, 0x03, 0x04, 0x05, - 0x06, 0x07, 0x07, 0x08, 0x07, 0x02, 0x05, 0x03, 0x03, 0x02, 0x07, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x01, - 0x01, 0x00, 0x02, 0x04, 0x05, 0x01, 0x70, 0x01, 0x05, 0x05, 0x05, 0x03, 0x01, 0x00, 0x02, 0x06, 0x0d, 0x02, - 0x7f, 0x01, 0x41, 0xc0, 0x91, 0x04, 0x0b, 0x7f, 0x00, 0x41, 0x00, 0x0b, 0x07, 0x1a, 0x03, 0x06, 0x6d, 0x65, - 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x06, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 0x06, 0x04, 0x6d, 0x61, - 0x69, 0x6e, 0x00, 0x07, 0x09, 0x0a, 0x01, 0x00, 0x41, 0x01, 0x0b, 0x04, 0x1a, 0x18, 0x1c, 0x1e, 0x0a, 0x93, - 0x1a, 0x1c, 0x02, 0x00, 0x0b, 0x51, 0x01, 0x01, 0x7f, 0x02, 0x40, 0x02, 0x40, 0x23, 0x81, 0x80, 0x80, 0x80, - 0x00, 0x41, 0xa0, 0x89, 0x80, 0x80, 0x00, 0x6a, 0x28, 0x02, 0x00, 0x0d, 0x00, 0x23, 0x81, 0x80, 0x80, 0x80, - 0x00, 0x41, 0xa0, 0x89, 0x80, 0x80, 0x00, 0x6a, 0x41, 0x01, 0x36, 0x02, 0x00, 0x10, 0x85, 0x80, 0x80, 0x80, - 0x00, 0x10, 0x87, 0x80, 0x80, 0x80, 0x00, 0x21, 0x00, 0x10, 0x8e, 0x80, 0x80, 0x80, 0x00, 0x20, 0x00, 0x0d, - 0x01, 0x0f, 0x0b, 0x00, 0x0b, 0x20, 0x00, 0x10, 0x8c, 0x80, 0x80, 0x80, 0x00, 0x00, 0x0b, 0x11, 0x00, 0x41, - 0x80, 0x88, 0x80, 0x80, 0x00, 0x10, 0x95, 0x80, 0x80, 0x80, 0x00, 0x1a, 0x41, 0x00, 0x0b, 0x0f, 0x00, 0x20, - 0x00, 0x10, 0x80, 0x80, 0x80, 0x80, 0x00, 0x41, 0xff, 0xff, 0x03, 0x71, 0x0b, 0x11, 0x00, 0x20, 0x00, 0x20, - 0x01, 0x10, 0x81, 0x80, 0x80, 0x80, 0x00, 0x41, 0xff, 0xff, 0x03, 0x71, 0x0b, 0x15, 0x00, 0x20, 0x00, 0x20, - 0x01, 0x20, 0x02, 0x20, 0x03, 0x10, 0x82, 0x80, 0x80, 0x80, 0x00, 0x41, 0xff, 0xff, 0x03, 0x71, 0x0b, 0x15, - 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x20, 0x03, 0x10, 0x83, 0x80, 0x80, 0x80, 0x00, 0x41, 0xff, 0xff, - 0x03, 0x71, 0x0b, 0x0b, 0x00, 0x20, 0x00, 0x10, 0x84, 0x80, 0x80, 0x80, 0x00, 0x00, 0x0b, 0x02, 0x00, 0x0b, - 0x0e, 0x00, 0x10, 0x8d, 0x80, 0x80, 0x80, 0x00, 0x10, 0x90, 0x80, 0x80, 0x80, 0x00, 0x0b, 0x08, 0x00, 0x41, - 0xa4, 0x89, 0x80, 0x80, 0x00, 0x0b, 0xa3, 0x03, 0x01, 0x03, 0x7f, 0x02, 0x40, 0x10, 0x8f, 0x80, 0x80, 0x80, - 0x00, 0x28, 0x02, 0x00, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x03, 0x40, 0x02, 0x40, 0x20, 0x00, 0x28, 0x02, 0x14, - 0x20, 0x00, 0x28, 0x02, 0x18, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x41, 0x00, 0x41, 0x00, 0x20, 0x00, 0x28, 0x02, - 0x20, 0x11, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x1a, 0x0b, 0x02, 0x40, 0x20, 0x00, - 0x28, 0x02, 0x04, 0x22, 0x01, 0x20, 0x00, 0x28, 0x02, 0x08, 0x22, 0x02, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x20, - 0x01, 0x20, 0x02, 0x6b, 0xac, 0x41, 0x01, 0x20, 0x00, 0x28, 0x02, 0x24, 0x11, 0x81, 0x80, 0x80, 0x80, 0x00, - 0x80, 0x80, 0x80, 0x80, 0x00, 0x1a, 0x0b, 0x20, 0x00, 0x28, 0x02, 0x34, 0x22, 0x00, 0x0d, 0x00, 0x0b, 0x0b, - 0x02, 0x40, 0x41, 0x00, 0x28, 0x02, 0xa8, 0x89, 0x80, 0x80, 0x00, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x02, 0x40, - 0x20, 0x00, 0x28, 0x02, 0x14, 0x20, 0x00, 0x28, 0x02, 0x18, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x41, 0x00, 0x41, - 0x00, 0x20, 0x00, 0x28, 0x02, 0x20, 0x11, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x1a, - 0x0b, 0x20, 0x00, 0x28, 0x02, 0x04, 0x22, 0x01, 0x20, 0x00, 0x28, 0x02, 0x08, 0x22, 0x02, 0x46, 0x0d, 0x00, - 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x6b, 0xac, 0x41, 0x01, 0x20, 0x00, 0x28, 0x02, 0x24, 0x11, 0x81, 0x80, - 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x1a, 0x0b, 0x02, 0x40, 0x41, 0x00, 0x28, 0x02, 0x90, 0x89, - 0x80, 0x80, 0x00, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x00, 0x28, 0x02, 0x14, 0x20, 0x00, 0x28, - 0x02, 0x18, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x41, 0x00, 0x41, 0x00, 0x20, 0x00, 0x28, 0x02, 0x20, 0x11, 0x80, - 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x1a, 0x0b, 0x20, 0x00, 0x28, 0x02, 0x04, 0x22, 0x01, - 0x20, 0x00, 0x28, 0x02, 0x08, 0x22, 0x02, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x6b, 0xac, - 0x41, 0x01, 0x20, 0x00, 0x28, 0x02, 0x24, 0x11, 0x81, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, - 0x1a, 0x0b, 0x02, 0x40, 0x41, 0x00, 0x28, 0x02, 0xa8, 0x89, 0x80, 0x80, 0x00, 0x22, 0x00, 0x45, 0x0d, 0x00, - 0x02, 0x40, 0x20, 0x00, 0x28, 0x02, 0x14, 0x20, 0x00, 0x28, 0x02, 0x18, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x41, - 0x00, 0x41, 0x00, 0x20, 0x00, 0x28, 0x02, 0x20, 0x11, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, - 0x00, 0x1a, 0x0b, 0x20, 0x00, 0x28, 0x02, 0x04, 0x22, 0x01, 0x20, 0x00, 0x28, 0x02, 0x08, 0x22, 0x02, 0x46, - 0x0d, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x6b, 0xac, 0x41, 0x01, 0x20, 0x00, 0x28, 0x02, 0x24, 0x11, - 0x81, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x1a, 0x0b, 0x0b, 0x5c, 0x01, 0x01, 0x7f, 0x20, - 0x00, 0x20, 0x00, 0x28, 0x02, 0x3c, 0x22, 0x01, 0x41, 0x7f, 0x6a, 0x20, 0x01, 0x72, 0x36, 0x02, 0x3c, 0x02, - 0x40, 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x01, 0x41, 0x08, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x00, 0x20, 0x01, - 0x41, 0x20, 0x72, 0x36, 0x02, 0x00, 0x41, 0x7f, 0x0f, 0x0b, 0x20, 0x00, 0x42, 0x00, 0x37, 0x02, 0x04, 0x20, - 0x00, 0x20, 0x00, 0x28, 0x02, 0x28, 0x22, 0x01, 0x36, 0x02, 0x18, 0x20, 0x00, 0x20, 0x01, 0x36, 0x02, 0x14, - 0x20, 0x00, 0x20, 0x01, 0x20, 0x00, 0x28, 0x02, 0x2c, 0x6a, 0x36, 0x02, 0x10, 0x41, 0x00, 0x0b, 0xa8, 0x02, - 0x01, 0x05, 0x7f, 0x20, 0x02, 0x20, 0x01, 0x6c, 0x21, 0x04, 0x02, 0x40, 0x02, 0x40, 0x20, 0x03, 0x28, 0x02, - 0x10, 0x22, 0x05, 0x0d, 0x00, 0x41, 0x00, 0x21, 0x06, 0x20, 0x03, 0x10, 0x91, 0x80, 0x80, 0x80, 0x00, 0x0d, - 0x01, 0x20, 0x03, 0x28, 0x02, 0x10, 0x21, 0x05, 0x0b, 0x02, 0x40, 0x20, 0x05, 0x20, 0x03, 0x28, 0x02, 0x14, - 0x22, 0x07, 0x6b, 0x20, 0x04, 0x4f, 0x0d, 0x00, 0x20, 0x03, 0x20, 0x00, 0x20, 0x04, 0x20, 0x03, 0x28, 0x02, - 0x20, 0x11, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x21, 0x06, 0x0c, 0x01, 0x0b, 0x41, - 0x00, 0x21, 0x08, 0x02, 0x40, 0x02, 0x40, 0x20, 0x04, 0x0d, 0x00, 0x20, 0x04, 0x21, 0x05, 0x0c, 0x01, 0x0b, - 0x41, 0x00, 0x21, 0x05, 0x02, 0x40, 0x20, 0x03, 0x28, 0x02, 0x40, 0x41, 0x00, 0x4e, 0x0d, 0x00, 0x20, 0x04, - 0x21, 0x05, 0x0c, 0x01, 0x0b, 0x20, 0x00, 0x20, 0x04, 0x6a, 0x21, 0x06, 0x02, 0x40, 0x03, 0x40, 0x20, 0x06, - 0x20, 0x05, 0x6a, 0x41, 0x7f, 0x6a, 0x2d, 0x00, 0x00, 0x41, 0x0a, 0x46, 0x0d, 0x01, 0x20, 0x04, 0x20, 0x05, - 0x41, 0x7f, 0x6a, 0x22, 0x05, 0x6a, 0x0d, 0x00, 0x0b, 0x41, 0x00, 0x21, 0x08, 0x20, 0x04, 0x21, 0x05, 0x0c, - 0x01, 0x0b, 0x20, 0x03, 0x20, 0x00, 0x20, 0x04, 0x20, 0x05, 0x6a, 0x22, 0x08, 0x20, 0x03, 0x28, 0x02, 0x20, - 0x11, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x22, 0x06, 0x20, 0x08, 0x49, 0x0d, 0x01, - 0x20, 0x08, 0x20, 0x00, 0x6a, 0x21, 0x00, 0x41, 0x00, 0x20, 0x05, 0x6b, 0x21, 0x05, 0x20, 0x03, 0x28, 0x02, - 0x14, 0x21, 0x07, 0x0b, 0x20, 0x07, 0x20, 0x00, 0x20, 0x05, 0x10, 0x9f, 0x80, 0x80, 0x80, 0x00, 0x1a, 0x20, - 0x03, 0x20, 0x03, 0x28, 0x02, 0x14, 0x20, 0x05, 0x6a, 0x36, 0x02, 0x14, 0x20, 0x08, 0x20, 0x05, 0x6a, 0x21, - 0x06, 0x0b, 0x02, 0x40, 0x20, 0x06, 0x20, 0x04, 0x47, 0x0d, 0x00, 0x20, 0x02, 0x41, 0x00, 0x20, 0x01, 0x1b, - 0x0f, 0x0b, 0x20, 0x06, 0x20, 0x01, 0x6e, 0x0b, 0x24, 0x01, 0x01, 0x7f, 0x20, 0x00, 0x10, 0xa0, 0x80, 0x80, - 0x80, 0x00, 0x21, 0x02, 0x41, 0x7f, 0x41, 0x00, 0x20, 0x02, 0x20, 0x00, 0x41, 0x01, 0x20, 0x02, 0x20, 0x01, - 0x10, 0x92, 0x80, 0x80, 0x80, 0x00, 0x47, 0x1b, 0x0b, 0xb3, 0x01, 0x01, 0x03, 0x7f, 0x23, 0x80, 0x80, 0x80, - 0x80, 0x00, 0x41, 0x10, 0x6b, 0x22, 0x02, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, 0x02, 0x20, 0x01, 0x3a, - 0x00, 0x0f, 0x02, 0x40, 0x02, 0x40, 0x20, 0x00, 0x28, 0x02, 0x10, 0x22, 0x03, 0x0d, 0x00, 0x02, 0x40, 0x20, - 0x00, 0x10, 0x91, 0x80, 0x80, 0x80, 0x00, 0x45, 0x0d, 0x00, 0x41, 0x7f, 0x21, 0x03, 0x0c, 0x02, 0x0b, 0x20, - 0x00, 0x28, 0x02, 0x10, 0x21, 0x03, 0x0b, 0x02, 0x40, 0x20, 0x00, 0x28, 0x02, 0x14, 0x22, 0x04, 0x20, 0x03, - 0x46, 0x0d, 0x00, 0x20, 0x00, 0x28, 0x02, 0x40, 0x20, 0x01, 0x41, 0xff, 0x01, 0x71, 0x22, 0x03, 0x46, 0x0d, - 0x00, 0x20, 0x00, 0x20, 0x04, 0x41, 0x01, 0x6a, 0x36, 0x02, 0x14, 0x20, 0x04, 0x20, 0x01, 0x3a, 0x00, 0x00, - 0x0c, 0x01, 0x0b, 0x02, 0x40, 0x20, 0x00, 0x20, 0x02, 0x41, 0x0f, 0x6a, 0x41, 0x01, 0x20, 0x00, 0x28, 0x02, - 0x20, 0x11, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x41, 0x01, 0x46, 0x0d, 0x00, 0x41, - 0x7f, 0x21, 0x03, 0x0c, 0x01, 0x0b, 0x20, 0x02, 0x2d, 0x00, 0x0f, 0x21, 0x03, 0x0b, 0x20, 0x02, 0x41, 0x10, - 0x6a, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, 0x03, 0x0b, 0x6c, 0x00, 0x02, 0x40, 0x20, 0x00, 0x41, 0xa0, - 0x88, 0x80, 0x80, 0x00, 0x10, 0x93, 0x80, 0x80, 0x80, 0x00, 0x41, 0x00, 0x4e, 0x0d, 0x00, 0x41, 0x7f, 0x0f, - 0x0b, 0x02, 0x40, 0x41, 0x00, 0x28, 0x02, 0xe0, 0x88, 0x80, 0x80, 0x00, 0x41, 0x0a, 0x46, 0x0d, 0x00, 0x41, - 0x00, 0x28, 0x02, 0xb4, 0x88, 0x80, 0x80, 0x00, 0x22, 0x00, 0x41, 0x00, 0x28, 0x02, 0xb0, 0x88, 0x80, 0x80, - 0x00, 0x46, 0x0d, 0x00, 0x41, 0x00, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x36, 0x02, 0xb4, 0x88, 0x80, 0x80, 0x00, - 0x20, 0x00, 0x41, 0x0a, 0x3a, 0x00, 0x00, 0x41, 0x00, 0x0f, 0x0b, 0x41, 0xa0, 0x88, 0x80, 0x80, 0x00, 0x41, - 0x0a, 0x10, 0x94, 0x80, 0x80, 0x80, 0x00, 0x41, 0x1f, 0x75, 0x0b, 0x02, 0x00, 0x0b, 0x27, 0x00, 0x10, 0x96, - 0x80, 0x80, 0x80, 0x00, 0x02, 0x40, 0x20, 0x00, 0x10, 0x88, 0x80, 0x80, 0x80, 0x00, 0x22, 0x00, 0x0d, 0x00, - 0x41, 0x00, 0x0f, 0x0b, 0x41, 0x00, 0x20, 0x00, 0x36, 0x02, 0xac, 0x89, 0x80, 0x80, 0x00, 0x41, 0x7f, 0x0b, - 0x0d, 0x00, 0x20, 0x00, 0x28, 0x02, 0x38, 0x10, 0x97, 0x80, 0x80, 0x80, 0x00, 0x0b, 0x71, 0x01, 0x02, 0x7f, - 0x23, 0x80, 0x80, 0x80, 0x80, 0x00, 0x41, 0x10, 0x6b, 0x22, 0x03, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, 0x41, - 0x7f, 0x21, 0x04, 0x02, 0x40, 0x02, 0x40, 0x20, 0x02, 0x41, 0x7f, 0x4a, 0x0d, 0x00, 0x41, 0x00, 0x41, 0x1c, - 0x36, 0x02, 0xac, 0x89, 0x80, 0x80, 0x00, 0x0c, 0x01, 0x0b, 0x02, 0x40, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, - 0x20, 0x03, 0x41, 0x0c, 0x6a, 0x10, 0x8b, 0x80, 0x80, 0x80, 0x00, 0x22, 0x02, 0x45, 0x0d, 0x00, 0x41, 0x00, - 0x20, 0x02, 0x36, 0x02, 0xac, 0x89, 0x80, 0x80, 0x00, 0x41, 0x7f, 0x21, 0x04, 0x0c, 0x01, 0x0b, 0x20, 0x03, - 0x28, 0x02, 0x0c, 0x21, 0x04, 0x0b, 0x20, 0x03, 0x41, 0x10, 0x6a, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, - 0x04, 0x0b, 0xbb, 0x02, 0x01, 0x07, 0x7f, 0x23, 0x80, 0x80, 0x80, 0x80, 0x00, 0x41, 0x10, 0x6b, 0x22, 0x03, - 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, 0x03, 0x20, 0x02, 0x36, 0x02, 0x0c, 0x20, 0x03, 0x20, 0x01, 0x36, - 0x02, 0x08, 0x20, 0x03, 0x20, 0x00, 0x28, 0x02, 0x18, 0x22, 0x01, 0x36, 0x02, 0x00, 0x20, 0x03, 0x20, 0x00, - 0x28, 0x02, 0x14, 0x20, 0x01, 0x6b, 0x22, 0x04, 0x36, 0x02, 0x04, 0x41, 0x02, 0x21, 0x05, 0x02, 0x40, 0x02, - 0x40, 0x20, 0x00, 0x28, 0x02, 0x38, 0x20, 0x03, 0x41, 0x02, 0x10, 0x99, 0x80, 0x80, 0x80, 0x00, 0x22, 0x01, - 0x20, 0x04, 0x20, 0x02, 0x6a, 0x22, 0x06, 0x46, 0x0d, 0x00, 0x20, 0x03, 0x21, 0x04, 0x03, 0x40, 0x02, 0x40, - 0x20, 0x01, 0x41, 0x7f, 0x4a, 0x0d, 0x00, 0x41, 0x00, 0x21, 0x01, 0x20, 0x00, 0x41, 0x00, 0x36, 0x02, 0x18, - 0x20, 0x00, 0x42, 0x00, 0x37, 0x03, 0x10, 0x20, 0x00, 0x20, 0x00, 0x28, 0x02, 0x00, 0x41, 0x20, 0x72, 0x36, - 0x02, 0x00, 0x20, 0x05, 0x41, 0x02, 0x46, 0x0d, 0x03, 0x20, 0x02, 0x20, 0x04, 0x28, 0x02, 0x04, 0x6b, 0x21, - 0x01, 0x0c, 0x03, 0x0b, 0x20, 0x04, 0x20, 0x01, 0x20, 0x04, 0x28, 0x02, 0x04, 0x22, 0x07, 0x4b, 0x22, 0x08, - 0x41, 0x03, 0x74, 0x6a, 0x22, 0x09, 0x20, 0x09, 0x28, 0x02, 0x00, 0x20, 0x01, 0x20, 0x07, 0x41, 0x00, 0x20, - 0x08, 0x1b, 0x6b, 0x22, 0x07, 0x6a, 0x36, 0x02, 0x00, 0x20, 0x04, 0x41, 0x0c, 0x41, 0x04, 0x20, 0x08, 0x1b, - 0x6a, 0x22, 0x04, 0x20, 0x04, 0x28, 0x02, 0x00, 0x20, 0x07, 0x6b, 0x36, 0x02, 0x00, 0x20, 0x09, 0x21, 0x04, - 0x20, 0x06, 0x20, 0x01, 0x6b, 0x22, 0x06, 0x20, 0x00, 0x28, 0x02, 0x38, 0x20, 0x09, 0x20, 0x05, 0x20, 0x08, - 0x6b, 0x22, 0x05, 0x10, 0x99, 0x80, 0x80, 0x80, 0x00, 0x22, 0x01, 0x47, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x00, - 0x20, 0x00, 0x28, 0x02, 0x28, 0x22, 0x01, 0x36, 0x02, 0x18, 0x20, 0x00, 0x20, 0x01, 0x36, 0x02, 0x14, 0x20, - 0x00, 0x20, 0x01, 0x20, 0x00, 0x28, 0x02, 0x2c, 0x6a, 0x36, 0x02, 0x10, 0x20, 0x02, 0x21, 0x01, 0x0b, 0x20, - 0x03, 0x41, 0x10, 0x6a, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, 0x01, 0x0b, 0x66, 0x01, 0x02, 0x7f, 0x23, - 0x80, 0x80, 0x80, 0x80, 0x00, 0x41, 0x20, 0x6b, 0x22, 0x01, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, 0x02, 0x40, - 0x02, 0x40, 0x20, 0x00, 0x20, 0x01, 0x41, 0x08, 0x6a, 0x10, 0x89, 0x80, 0x80, 0x80, 0x00, 0x22, 0x00, 0x0d, - 0x00, 0x41, 0x3b, 0x21, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x08, 0x41, 0x02, 0x47, 0x0d, 0x00, 0x20, 0x01, 0x2d, - 0x00, 0x10, 0x41, 0x24, 0x71, 0x0d, 0x00, 0x41, 0x01, 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x41, 0x00, 0x21, 0x02, - 0x41, 0x00, 0x20, 0x00, 0x36, 0x02, 0xac, 0x89, 0x80, 0x80, 0x00, 0x0b, 0x20, 0x01, 0x41, 0x20, 0x6a, 0x24, - 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, 0x02, 0x0b, 0x3b, 0x00, 0x20, 0x00, 0x41, 0x81, 0x80, 0x80, 0x80, 0x00, - 0x36, 0x02, 0x20, 0x02, 0x40, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x41, 0xc0, 0x00, 0x71, 0x0d, 0x00, 0x20, 0x00, - 0x28, 0x02, 0x38, 0x10, 0x9b, 0x80, 0x80, 0x80, 0x00, 0x0d, 0x00, 0x20, 0x00, 0x41, 0x7f, 0x36, 0x02, 0x40, - 0x0b, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x10, 0x9a, 0x80, 0x80, 0x80, 0x00, 0x0b, 0x64, 0x01, 0x01, 0x7f, - 0x23, 0x80, 0x80, 0x80, 0x80, 0x00, 0x41, 0x10, 0x6b, 0x22, 0x03, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, 0x02, - 0x40, 0x02, 0x40, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x41, 0xff, 0x01, 0x71, 0x20, 0x03, 0x41, 0x08, 0x6a, - 0x10, 0x8a, 0x80, 0x80, 0x80, 0x00, 0x22, 0x02, 0x45, 0x0d, 0x00, 0x41, 0x00, 0x41, 0xc6, 0x00, 0x20, 0x02, - 0x20, 0x02, 0x41, 0xcc, 0x00, 0x46, 0x1b, 0x36, 0x02, 0xac, 0x89, 0x80, 0x80, 0x00, 0x42, 0x7f, 0x21, 0x01, - 0x0c, 0x01, 0x0b, 0x20, 0x03, 0x29, 0x03, 0x08, 0x21, 0x01, 0x0b, 0x20, 0x03, 0x41, 0x10, 0x6a, 0x24, 0x80, - 0x80, 0x80, 0x80, 0x00, 0x20, 0x01, 0x0b, 0x11, 0x00, 0x20, 0x00, 0x28, 0x02, 0x38, 0x20, 0x01, 0x20, 0x02, - 0x10, 0x9d, 0x80, 0x80, 0x80, 0x00, 0x0b, 0xee, 0x07, 0x01, 0x04, 0x7f, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, - 0x20, 0x02, 0x41, 0x20, 0x4b, 0x0d, 0x00, 0x20, 0x01, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x01, 0x20, 0x02, 0x45, - 0x0d, 0x01, 0x20, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x02, 0x41, 0x7f, 0x6a, 0x21, - 0x03, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x21, 0x04, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x22, 0x05, 0x41, 0x03, 0x71, - 0x45, 0x0d, 0x02, 0x20, 0x03, 0x45, 0x0d, 0x02, 0x20, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x01, 0x3a, 0x00, 0x01, - 0x20, 0x02, 0x41, 0x7e, 0x6a, 0x21, 0x03, 0x20, 0x00, 0x41, 0x02, 0x6a, 0x21, 0x04, 0x20, 0x01, 0x41, 0x02, - 0x6a, 0x22, 0x05, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x02, 0x20, 0x03, 0x45, 0x0d, 0x02, 0x20, 0x00, 0x20, 0x01, - 0x2d, 0x00, 0x02, 0x3a, 0x00, 0x02, 0x20, 0x02, 0x41, 0x7d, 0x6a, 0x21, 0x03, 0x20, 0x00, 0x41, 0x03, 0x6a, - 0x21, 0x04, 0x20, 0x01, 0x41, 0x03, 0x6a, 0x22, 0x05, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x02, 0x20, 0x03, 0x45, - 0x0d, 0x02, 0x20, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x03, 0x3a, 0x00, 0x03, 0x20, 0x02, 0x41, 0x7c, 0x6a, 0x21, - 0x03, 0x20, 0x00, 0x41, 0x04, 0x6a, 0x21, 0x04, 0x20, 0x01, 0x41, 0x04, 0x6a, 0x21, 0x05, 0x0c, 0x02, 0x0b, - 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0xfc, 0x0a, 0x00, 0x00, 0x20, 0x00, 0x0f, 0x0b, 0x20, 0x02, 0x21, 0x03, - 0x20, 0x00, 0x21, 0x04, 0x20, 0x01, 0x21, 0x05, 0x0b, 0x02, 0x40, 0x02, 0x40, 0x20, 0x04, 0x41, 0x03, 0x71, - 0x22, 0x02, 0x0d, 0x00, 0x02, 0x40, 0x02, 0x40, 0x20, 0x03, 0x41, 0x10, 0x4f, 0x0d, 0x00, 0x20, 0x03, 0x21, - 0x02, 0x0c, 0x01, 0x0b, 0x02, 0x40, 0x20, 0x03, 0x41, 0x70, 0x6a, 0x22, 0x02, 0x41, 0x10, 0x71, 0x0d, 0x00, - 0x20, 0x04, 0x20, 0x05, 0x29, 0x02, 0x00, 0x37, 0x02, 0x00, 0x20, 0x04, 0x20, 0x05, 0x29, 0x02, 0x08, 0x37, - 0x02, 0x08, 0x20, 0x04, 0x41, 0x10, 0x6a, 0x21, 0x04, 0x20, 0x05, 0x41, 0x10, 0x6a, 0x21, 0x05, 0x20, 0x02, - 0x21, 0x03, 0x0b, 0x20, 0x02, 0x41, 0x10, 0x49, 0x0d, 0x00, 0x20, 0x03, 0x21, 0x02, 0x03, 0x40, 0x20, 0x04, - 0x20, 0x05, 0x29, 0x02, 0x00, 0x37, 0x02, 0x00, 0x20, 0x04, 0x20, 0x05, 0x29, 0x02, 0x08, 0x37, 0x02, 0x08, - 0x20, 0x04, 0x20, 0x05, 0x29, 0x02, 0x10, 0x37, 0x02, 0x10, 0x20, 0x04, 0x20, 0x05, 0x29, 0x02, 0x18, 0x37, - 0x02, 0x18, 0x20, 0x04, 0x41, 0x20, 0x6a, 0x21, 0x04, 0x20, 0x05, 0x41, 0x20, 0x6a, 0x21, 0x05, 0x20, 0x02, - 0x41, 0x60, 0x6a, 0x22, 0x02, 0x41, 0x0f, 0x4b, 0x0d, 0x00, 0x0b, 0x0b, 0x02, 0x40, 0x20, 0x02, 0x41, 0x08, - 0x49, 0x0d, 0x00, 0x20, 0x04, 0x20, 0x05, 0x29, 0x02, 0x00, 0x37, 0x02, 0x00, 0x20, 0x05, 0x41, 0x08, 0x6a, - 0x21, 0x05, 0x20, 0x04, 0x41, 0x08, 0x6a, 0x21, 0x04, 0x0b, 0x02, 0x40, 0x20, 0x02, 0x41, 0x04, 0x71, 0x45, - 0x0d, 0x00, 0x20, 0x04, 0x20, 0x05, 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, 0x20, 0x05, 0x41, 0x04, 0x6a, 0x21, - 0x05, 0x20, 0x04, 0x41, 0x04, 0x6a, 0x21, 0x04, 0x0b, 0x02, 0x40, 0x20, 0x02, 0x41, 0x02, 0x71, 0x45, 0x0d, - 0x00, 0x20, 0x04, 0x20, 0x05, 0x2f, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x20, 0x04, 0x41, 0x02, 0x6a, 0x21, 0x04, - 0x20, 0x05, 0x41, 0x02, 0x6a, 0x21, 0x05, 0x0b, 0x20, 0x02, 0x41, 0x01, 0x71, 0x45, 0x0d, 0x01, 0x20, 0x04, - 0x20, 0x05, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x00, 0x0f, 0x0b, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, - 0x02, 0x40, 0x02, 0x40, 0x20, 0x03, 0x41, 0x20, 0x49, 0x0d, 0x00, 0x20, 0x04, 0x20, 0x05, 0x28, 0x02, 0x00, - 0x22, 0x03, 0x3a, 0x00, 0x00, 0x02, 0x40, 0x02, 0x40, 0x20, 0x02, 0x41, 0x7f, 0x6a, 0x0e, 0x03, 0x03, 0x00, - 0x01, 0x03, 0x0b, 0x20, 0x04, 0x20, 0x03, 0x41, 0x08, 0x76, 0x3a, 0x00, 0x01, 0x20, 0x04, 0x20, 0x05, 0x41, - 0x06, 0x6a, 0x29, 0x01, 0x00, 0x37, 0x02, 0x06, 0x20, 0x04, 0x20, 0x05, 0x28, 0x02, 0x04, 0x41, 0x10, 0x74, - 0x20, 0x03, 0x41, 0x10, 0x76, 0x72, 0x36, 0x02, 0x02, 0x20, 0x04, 0x41, 0x12, 0x6a, 0x21, 0x02, 0x20, 0x05, - 0x41, 0x12, 0x6a, 0x21, 0x01, 0x41, 0x0e, 0x21, 0x06, 0x20, 0x05, 0x41, 0x0e, 0x6a, 0x28, 0x01, 0x00, 0x21, - 0x05, 0x41, 0x0e, 0x21, 0x03, 0x0c, 0x03, 0x0b, 0x20, 0x04, 0x20, 0x05, 0x41, 0x05, 0x6a, 0x29, 0x00, 0x00, - 0x37, 0x02, 0x05, 0x20, 0x04, 0x20, 0x05, 0x28, 0x02, 0x04, 0x41, 0x18, 0x74, 0x20, 0x03, 0x41, 0x08, 0x76, - 0x72, 0x36, 0x02, 0x01, 0x20, 0x04, 0x41, 0x11, 0x6a, 0x21, 0x02, 0x20, 0x05, 0x41, 0x11, 0x6a, 0x21, 0x01, - 0x41, 0x0d, 0x21, 0x06, 0x20, 0x05, 0x41, 0x0d, 0x6a, 0x28, 0x00, 0x00, 0x21, 0x05, 0x41, 0x0f, 0x21, 0x03, - 0x0c, 0x02, 0x0b, 0x02, 0x40, 0x02, 0x40, 0x20, 0x03, 0x41, 0x10, 0x4f, 0x0d, 0x00, 0x20, 0x04, 0x21, 0x02, - 0x20, 0x05, 0x21, 0x01, 0x0c, 0x01, 0x0b, 0x20, 0x04, 0x20, 0x05, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x20, - 0x04, 0x20, 0x05, 0x28, 0x00, 0x01, 0x36, 0x00, 0x01, 0x20, 0x04, 0x20, 0x05, 0x29, 0x00, 0x05, 0x37, 0x00, - 0x05, 0x20, 0x04, 0x20, 0x05, 0x2f, 0x00, 0x0d, 0x3b, 0x00, 0x0d, 0x20, 0x04, 0x20, 0x05, 0x2d, 0x00, 0x0f, - 0x3a, 0x00, 0x0f, 0x20, 0x04, 0x41, 0x10, 0x6a, 0x21, 0x02, 0x20, 0x05, 0x41, 0x10, 0x6a, 0x21, 0x01, 0x0b, - 0x20, 0x03, 0x41, 0x08, 0x71, 0x0d, 0x02, 0x0c, 0x03, 0x0b, 0x20, 0x04, 0x20, 0x03, 0x41, 0x10, 0x76, 0x3a, - 0x00, 0x02, 0x20, 0x04, 0x20, 0x03, 0x41, 0x08, 0x76, 0x3a, 0x00, 0x01, 0x20, 0x04, 0x20, 0x05, 0x41, 0x07, - 0x6a, 0x29, 0x00, 0x00, 0x37, 0x02, 0x07, 0x20, 0x04, 0x20, 0x05, 0x28, 0x02, 0x04, 0x41, 0x08, 0x74, 0x20, - 0x03, 0x41, 0x18, 0x76, 0x72, 0x36, 0x02, 0x03, 0x20, 0x04, 0x41, 0x13, 0x6a, 0x21, 0x02, 0x20, 0x05, 0x41, - 0x13, 0x6a, 0x21, 0x01, 0x41, 0x0f, 0x21, 0x06, 0x20, 0x05, 0x41, 0x0f, 0x6a, 0x28, 0x00, 0x00, 0x21, 0x05, - 0x41, 0x0d, 0x21, 0x03, 0x0b, 0x20, 0x04, 0x20, 0x06, 0x6a, 0x20, 0x05, 0x36, 0x02, 0x00, 0x0b, 0x20, 0x02, - 0x20, 0x01, 0x29, 0x00, 0x00, 0x37, 0x00, 0x00, 0x20, 0x02, 0x41, 0x08, 0x6a, 0x21, 0x02, 0x20, 0x01, 0x41, - 0x08, 0x6a, 0x21, 0x01, 0x0b, 0x02, 0x40, 0x20, 0x03, 0x41, 0x04, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x02, 0x20, - 0x01, 0x28, 0x00, 0x00, 0x36, 0x00, 0x00, 0x20, 0x02, 0x41, 0x04, 0x6a, 0x21, 0x02, 0x20, 0x01, 0x41, 0x04, - 0x6a, 0x21, 0x01, 0x0b, 0x02, 0x40, 0x20, 0x03, 0x41, 0x02, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x02, 0x20, 0x01, - 0x2f, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x20, 0x02, 0x41, 0x02, 0x6a, 0x21, 0x02, 0x20, 0x01, 0x41, 0x02, 0x6a, - 0x21, 0x01, 0x0b, 0x20, 0x03, 0x41, 0x01, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x02, 0x20, 0x01, 0x2d, 0x00, 0x00, - 0x3a, 0x00, 0x00, 0x0b, 0x20, 0x00, 0x0b, 0xcf, 0x01, 0x01, 0x03, 0x7f, 0x20, 0x00, 0x21, 0x01, 0x02, 0x40, - 0x02, 0x40, 0x20, 0x00, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x0d, - 0x00, 0x20, 0x00, 0x20, 0x00, 0x6b, 0x0f, 0x0b, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x22, 0x01, 0x41, 0x03, 0x71, - 0x45, 0x0d, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x45, 0x0d, 0x01, 0x20, 0x00, 0x41, 0x02, 0x6a, 0x22, 0x01, - 0x41, 0x03, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x45, 0x0d, 0x01, 0x20, 0x00, 0x41, 0x03, - 0x6a, 0x22, 0x01, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x45, 0x0d, 0x01, 0x20, - 0x00, 0x41, 0x04, 0x6a, 0x22, 0x01, 0x41, 0x03, 0x71, 0x0d, 0x01, 0x0b, 0x20, 0x01, 0x41, 0x7c, 0x6a, 0x21, - 0x02, 0x20, 0x01, 0x41, 0x7b, 0x6a, 0x21, 0x01, 0x03, 0x40, 0x20, 0x01, 0x41, 0x04, 0x6a, 0x21, 0x01, 0x41, - 0x80, 0x82, 0x84, 0x08, 0x20, 0x02, 0x41, 0x04, 0x6a, 0x22, 0x02, 0x28, 0x02, 0x00, 0x22, 0x03, 0x6b, 0x20, - 0x03, 0x72, 0x41, 0x80, 0x81, 0x82, 0x84, 0x78, 0x71, 0x41, 0x80, 0x81, 0x82, 0x84, 0x78, 0x46, 0x0d, 0x00, - 0x0b, 0x03, 0x40, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x21, 0x01, 0x20, 0x02, 0x2d, 0x00, 0x00, 0x21, 0x03, 0x20, - 0x02, 0x41, 0x01, 0x6a, 0x21, 0x02, 0x20, 0x03, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x01, 0x20, 0x00, 0x6b, 0x0b, - 0x0b, 0x9d, 0x01, 0x02, 0x00, 0x41, 0x80, 0x08, 0x0b, 0x1c, 0x0a, 0x0a, 0x09, 0x48, 0x65, 0x6c, 0x6c, 0x6f, - 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x4f, 0x63, 0x72, 0x65, 0x21, 0x0a, - 0x0a, 0x00, 0x00, 0x41, 0xa0, 0x08, 0x0b, 0x74, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xb8, 0x04, 0x00, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00}; + 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x35, 0x09, 0x60, + 0x03, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x03, 0x7f, 0x7e, 0x7f, 0x01, + 0x7e, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, + 0x60, 0x04, 0x7f, 0x7e, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x04, 0x7f, 0x7f, + 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x00, 0x60, 0x00, 0x00, 0x60, + 0x00, 0x01, 0x7f, 0x02, 0xb0, 0x01, 0x05, 0x16, 0x77, 0x61, 0x73, 0x69, + 0x5f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, 0x72, + 0x65, 0x76, 0x69, 0x65, 0x77, 0x31, 0x08, 0x66, 0x64, 0x5f, 0x63, 0x6c, + 0x6f, 0x73, 0x65, 0x00, 0x02, 0x16, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x73, + 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x76, + 0x69, 0x65, 0x77, 0x31, 0x0d, 0x66, 0x64, 0x5f, 0x66, 0x64, 0x73, 0x74, + 0x61, 0x74, 0x5f, 0x67, 0x65, 0x74, 0x00, 0x03, 0x16, 0x77, 0x61, 0x73, + 0x69, 0x5f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, + 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x31, 0x07, 0x66, 0x64, 0x5f, 0x73, + 0x65, 0x65, 0x6b, 0x00, 0x04, 0x16, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x73, + 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x76, + 0x69, 0x65, 0x77, 0x31, 0x08, 0x66, 0x64, 0x5f, 0x77, 0x72, 0x69, 0x74, + 0x65, 0x00, 0x05, 0x16, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x73, 0x6e, 0x61, + 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, + 0x77, 0x31, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x5f, 0x65, 0x78, 0x69, 0x74, + 0x00, 0x06, 0x03, 0x1d, 0x1c, 0x07, 0x07, 0x08, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x07, 0x08, 0x07, 0x02, 0x05, 0x03, 0x03, 0x02, 0x07, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x00, 0x01, 0x01, 0x00, 0x02, 0x04, 0x05, 0x01, + 0x70, 0x01, 0x05, 0x05, 0x05, 0x03, 0x01, 0x00, 0x02, 0x06, 0x0d, 0x02, + 0x7f, 0x01, 0x41, 0xc0, 0x91, 0x04, 0x0b, 0x7f, 0x00, 0x41, 0x00, 0x0b, + 0x07, 0x1a, 0x03, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, + 0x06, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 0x06, 0x04, 0x6d, 0x61, + 0x69, 0x6e, 0x00, 0x07, 0x09, 0x0a, 0x01, 0x00, 0x41, 0x01, 0x0b, 0x04, + 0x1a, 0x18, 0x1c, 0x1e, 0x0a, 0x93, 0x1a, 0x1c, 0x02, 0x00, 0x0b, 0x51, + 0x01, 0x01, 0x7f, 0x02, 0x40, 0x02, 0x40, 0x23, 0x81, 0x80, 0x80, 0x80, + 0x00, 0x41, 0xa0, 0x89, 0x80, 0x80, 0x00, 0x6a, 0x28, 0x02, 0x00, 0x0d, + 0x00, 0x23, 0x81, 0x80, 0x80, 0x80, 0x00, 0x41, 0xa0, 0x89, 0x80, 0x80, + 0x00, 0x6a, 0x41, 0x01, 0x36, 0x02, 0x00, 0x10, 0x85, 0x80, 0x80, 0x80, + 0x00, 0x10, 0x87, 0x80, 0x80, 0x80, 0x00, 0x21, 0x00, 0x10, 0x8e, 0x80, + 0x80, 0x80, 0x00, 0x20, 0x00, 0x0d, 0x01, 0x0f, 0x0b, 0x00, 0x0b, 0x20, + 0x00, 0x10, 0x8c, 0x80, 0x80, 0x80, 0x00, 0x00, 0x0b, 0x11, 0x00, 0x41, + 0x80, 0x88, 0x80, 0x80, 0x00, 0x10, 0x95, 0x80, 0x80, 0x80, 0x00, 0x1a, + 0x41, 0x00, 0x0b, 0x0f, 0x00, 0x20, 0x00, 0x10, 0x80, 0x80, 0x80, 0x80, + 0x00, 0x41, 0xff, 0xff, 0x03, 0x71, 0x0b, 0x11, 0x00, 0x20, 0x00, 0x20, + 0x01, 0x10, 0x81, 0x80, 0x80, 0x80, 0x00, 0x41, 0xff, 0xff, 0x03, 0x71, + 0x0b, 0x15, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x20, 0x03, 0x10, + 0x82, 0x80, 0x80, 0x80, 0x00, 0x41, 0xff, 0xff, 0x03, 0x71, 0x0b, 0x15, + 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x20, 0x03, 0x10, 0x83, 0x80, + 0x80, 0x80, 0x00, 0x41, 0xff, 0xff, 0x03, 0x71, 0x0b, 0x0b, 0x00, 0x20, + 0x00, 0x10, 0x84, 0x80, 0x80, 0x80, 0x00, 0x00, 0x0b, 0x02, 0x00, 0x0b, + 0x0e, 0x00, 0x10, 0x8d, 0x80, 0x80, 0x80, 0x00, 0x10, 0x90, 0x80, 0x80, + 0x80, 0x00, 0x0b, 0x08, 0x00, 0x41, 0xa4, 0x89, 0x80, 0x80, 0x00, 0x0b, + 0xa3, 0x03, 0x01, 0x03, 0x7f, 0x02, 0x40, 0x10, 0x8f, 0x80, 0x80, 0x80, + 0x00, 0x28, 0x02, 0x00, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x03, 0x40, 0x02, + 0x40, 0x20, 0x00, 0x28, 0x02, 0x14, 0x20, 0x00, 0x28, 0x02, 0x18, 0x46, + 0x0d, 0x00, 0x20, 0x00, 0x41, 0x00, 0x41, 0x00, 0x20, 0x00, 0x28, 0x02, + 0x20, 0x11, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, + 0x1a, 0x0b, 0x02, 0x40, 0x20, 0x00, 0x28, 0x02, 0x04, 0x22, 0x01, 0x20, + 0x00, 0x28, 0x02, 0x08, 0x22, 0x02, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x20, + 0x01, 0x20, 0x02, 0x6b, 0xac, 0x41, 0x01, 0x20, 0x00, 0x28, 0x02, 0x24, + 0x11, 0x81, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x1a, + 0x0b, 0x20, 0x00, 0x28, 0x02, 0x34, 0x22, 0x00, 0x0d, 0x00, 0x0b, 0x0b, + 0x02, 0x40, 0x41, 0x00, 0x28, 0x02, 0xa8, 0x89, 0x80, 0x80, 0x00, 0x22, + 0x00, 0x45, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x00, 0x28, 0x02, 0x14, 0x20, + 0x00, 0x28, 0x02, 0x18, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x41, 0x00, 0x41, + 0x00, 0x20, 0x00, 0x28, 0x02, 0x20, 0x11, 0x80, 0x80, 0x80, 0x80, 0x00, + 0x80, 0x80, 0x80, 0x80, 0x00, 0x1a, 0x0b, 0x20, 0x00, 0x28, 0x02, 0x04, + 0x22, 0x01, 0x20, 0x00, 0x28, 0x02, 0x08, 0x22, 0x02, 0x46, 0x0d, 0x00, + 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x6b, 0xac, 0x41, 0x01, 0x20, 0x00, + 0x28, 0x02, 0x24, 0x11, 0x81, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, + 0x80, 0x00, 0x1a, 0x0b, 0x02, 0x40, 0x41, 0x00, 0x28, 0x02, 0x90, 0x89, + 0x80, 0x80, 0x00, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x00, + 0x28, 0x02, 0x14, 0x20, 0x00, 0x28, 0x02, 0x18, 0x46, 0x0d, 0x00, 0x20, + 0x00, 0x41, 0x00, 0x41, 0x00, 0x20, 0x00, 0x28, 0x02, 0x20, 0x11, 0x80, + 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x1a, 0x0b, 0x20, + 0x00, 0x28, 0x02, 0x04, 0x22, 0x01, 0x20, 0x00, 0x28, 0x02, 0x08, 0x22, + 0x02, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x6b, 0xac, + 0x41, 0x01, 0x20, 0x00, 0x28, 0x02, 0x24, 0x11, 0x81, 0x80, 0x80, 0x80, + 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x1a, 0x0b, 0x02, 0x40, 0x41, 0x00, + 0x28, 0x02, 0xa8, 0x89, 0x80, 0x80, 0x00, 0x22, 0x00, 0x45, 0x0d, 0x00, + 0x02, 0x40, 0x20, 0x00, 0x28, 0x02, 0x14, 0x20, 0x00, 0x28, 0x02, 0x18, + 0x46, 0x0d, 0x00, 0x20, 0x00, 0x41, 0x00, 0x41, 0x00, 0x20, 0x00, 0x28, + 0x02, 0x20, 0x11, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, + 0x00, 0x1a, 0x0b, 0x20, 0x00, 0x28, 0x02, 0x04, 0x22, 0x01, 0x20, 0x00, + 0x28, 0x02, 0x08, 0x22, 0x02, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x20, 0x01, + 0x20, 0x02, 0x6b, 0xac, 0x41, 0x01, 0x20, 0x00, 0x28, 0x02, 0x24, 0x11, + 0x81, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x1a, 0x0b, + 0x0b, 0x5c, 0x01, 0x01, 0x7f, 0x20, 0x00, 0x20, 0x00, 0x28, 0x02, 0x3c, + 0x22, 0x01, 0x41, 0x7f, 0x6a, 0x20, 0x01, 0x72, 0x36, 0x02, 0x3c, 0x02, + 0x40, 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x01, 0x41, 0x08, 0x71, 0x45, + 0x0d, 0x00, 0x20, 0x00, 0x20, 0x01, 0x41, 0x20, 0x72, 0x36, 0x02, 0x00, + 0x41, 0x7f, 0x0f, 0x0b, 0x20, 0x00, 0x42, 0x00, 0x37, 0x02, 0x04, 0x20, + 0x00, 0x20, 0x00, 0x28, 0x02, 0x28, 0x22, 0x01, 0x36, 0x02, 0x18, 0x20, + 0x00, 0x20, 0x01, 0x36, 0x02, 0x14, 0x20, 0x00, 0x20, 0x01, 0x20, 0x00, + 0x28, 0x02, 0x2c, 0x6a, 0x36, 0x02, 0x10, 0x41, 0x00, 0x0b, 0xa8, 0x02, + 0x01, 0x05, 0x7f, 0x20, 0x02, 0x20, 0x01, 0x6c, 0x21, 0x04, 0x02, 0x40, + 0x02, 0x40, 0x20, 0x03, 0x28, 0x02, 0x10, 0x22, 0x05, 0x0d, 0x00, 0x41, + 0x00, 0x21, 0x06, 0x20, 0x03, 0x10, 0x91, 0x80, 0x80, 0x80, 0x00, 0x0d, + 0x01, 0x20, 0x03, 0x28, 0x02, 0x10, 0x21, 0x05, 0x0b, 0x02, 0x40, 0x20, + 0x05, 0x20, 0x03, 0x28, 0x02, 0x14, 0x22, 0x07, 0x6b, 0x20, 0x04, 0x4f, + 0x0d, 0x00, 0x20, 0x03, 0x20, 0x00, 0x20, 0x04, 0x20, 0x03, 0x28, 0x02, + 0x20, 0x11, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, + 0x21, 0x06, 0x0c, 0x01, 0x0b, 0x41, 0x00, 0x21, 0x08, 0x02, 0x40, 0x02, + 0x40, 0x20, 0x04, 0x0d, 0x00, 0x20, 0x04, 0x21, 0x05, 0x0c, 0x01, 0x0b, + 0x41, 0x00, 0x21, 0x05, 0x02, 0x40, 0x20, 0x03, 0x28, 0x02, 0x40, 0x41, + 0x00, 0x4e, 0x0d, 0x00, 0x20, 0x04, 0x21, 0x05, 0x0c, 0x01, 0x0b, 0x20, + 0x00, 0x20, 0x04, 0x6a, 0x21, 0x06, 0x02, 0x40, 0x03, 0x40, 0x20, 0x06, + 0x20, 0x05, 0x6a, 0x41, 0x7f, 0x6a, 0x2d, 0x00, 0x00, 0x41, 0x0a, 0x46, + 0x0d, 0x01, 0x20, 0x04, 0x20, 0x05, 0x41, 0x7f, 0x6a, 0x22, 0x05, 0x6a, + 0x0d, 0x00, 0x0b, 0x41, 0x00, 0x21, 0x08, 0x20, 0x04, 0x21, 0x05, 0x0c, + 0x01, 0x0b, 0x20, 0x03, 0x20, 0x00, 0x20, 0x04, 0x20, 0x05, 0x6a, 0x22, + 0x08, 0x20, 0x03, 0x28, 0x02, 0x20, 0x11, 0x80, 0x80, 0x80, 0x80, 0x00, + 0x80, 0x80, 0x80, 0x80, 0x00, 0x22, 0x06, 0x20, 0x08, 0x49, 0x0d, 0x01, + 0x20, 0x08, 0x20, 0x00, 0x6a, 0x21, 0x00, 0x41, 0x00, 0x20, 0x05, 0x6b, + 0x21, 0x05, 0x20, 0x03, 0x28, 0x02, 0x14, 0x21, 0x07, 0x0b, 0x20, 0x07, + 0x20, 0x00, 0x20, 0x05, 0x10, 0x9f, 0x80, 0x80, 0x80, 0x00, 0x1a, 0x20, + 0x03, 0x20, 0x03, 0x28, 0x02, 0x14, 0x20, 0x05, 0x6a, 0x36, 0x02, 0x14, + 0x20, 0x08, 0x20, 0x05, 0x6a, 0x21, 0x06, 0x0b, 0x02, 0x40, 0x20, 0x06, + 0x20, 0x04, 0x47, 0x0d, 0x00, 0x20, 0x02, 0x41, 0x00, 0x20, 0x01, 0x1b, + 0x0f, 0x0b, 0x20, 0x06, 0x20, 0x01, 0x6e, 0x0b, 0x24, 0x01, 0x01, 0x7f, + 0x20, 0x00, 0x10, 0xa0, 0x80, 0x80, 0x80, 0x00, 0x21, 0x02, 0x41, 0x7f, + 0x41, 0x00, 0x20, 0x02, 0x20, 0x00, 0x41, 0x01, 0x20, 0x02, 0x20, 0x01, + 0x10, 0x92, 0x80, 0x80, 0x80, 0x00, 0x47, 0x1b, 0x0b, 0xb3, 0x01, 0x01, + 0x03, 0x7f, 0x23, 0x80, 0x80, 0x80, 0x80, 0x00, 0x41, 0x10, 0x6b, 0x22, + 0x02, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, 0x02, 0x20, 0x01, 0x3a, + 0x00, 0x0f, 0x02, 0x40, 0x02, 0x40, 0x20, 0x00, 0x28, 0x02, 0x10, 0x22, + 0x03, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x00, 0x10, 0x91, 0x80, 0x80, 0x80, + 0x00, 0x45, 0x0d, 0x00, 0x41, 0x7f, 0x21, 0x03, 0x0c, 0x02, 0x0b, 0x20, + 0x00, 0x28, 0x02, 0x10, 0x21, 0x03, 0x0b, 0x02, 0x40, 0x20, 0x00, 0x28, + 0x02, 0x14, 0x22, 0x04, 0x20, 0x03, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x28, + 0x02, 0x40, 0x20, 0x01, 0x41, 0xff, 0x01, 0x71, 0x22, 0x03, 0x46, 0x0d, + 0x00, 0x20, 0x00, 0x20, 0x04, 0x41, 0x01, 0x6a, 0x36, 0x02, 0x14, 0x20, + 0x04, 0x20, 0x01, 0x3a, 0x00, 0x00, 0x0c, 0x01, 0x0b, 0x02, 0x40, 0x20, + 0x00, 0x20, 0x02, 0x41, 0x0f, 0x6a, 0x41, 0x01, 0x20, 0x00, 0x28, 0x02, + 0x20, 0x11, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, + 0x41, 0x01, 0x46, 0x0d, 0x00, 0x41, 0x7f, 0x21, 0x03, 0x0c, 0x01, 0x0b, + 0x20, 0x02, 0x2d, 0x00, 0x0f, 0x21, 0x03, 0x0b, 0x20, 0x02, 0x41, 0x10, + 0x6a, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, 0x03, 0x0b, 0x6c, 0x00, + 0x02, 0x40, 0x20, 0x00, 0x41, 0xa0, 0x88, 0x80, 0x80, 0x00, 0x10, 0x93, + 0x80, 0x80, 0x80, 0x00, 0x41, 0x00, 0x4e, 0x0d, 0x00, 0x41, 0x7f, 0x0f, + 0x0b, 0x02, 0x40, 0x41, 0x00, 0x28, 0x02, 0xe0, 0x88, 0x80, 0x80, 0x00, + 0x41, 0x0a, 0x46, 0x0d, 0x00, 0x41, 0x00, 0x28, 0x02, 0xb4, 0x88, 0x80, + 0x80, 0x00, 0x22, 0x00, 0x41, 0x00, 0x28, 0x02, 0xb0, 0x88, 0x80, 0x80, + 0x00, 0x46, 0x0d, 0x00, 0x41, 0x00, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x36, + 0x02, 0xb4, 0x88, 0x80, 0x80, 0x00, 0x20, 0x00, 0x41, 0x0a, 0x3a, 0x00, + 0x00, 0x41, 0x00, 0x0f, 0x0b, 0x41, 0xa0, 0x88, 0x80, 0x80, 0x00, 0x41, + 0x0a, 0x10, 0x94, 0x80, 0x80, 0x80, 0x00, 0x41, 0x1f, 0x75, 0x0b, 0x02, + 0x00, 0x0b, 0x27, 0x00, 0x10, 0x96, 0x80, 0x80, 0x80, 0x00, 0x02, 0x40, + 0x20, 0x00, 0x10, 0x88, 0x80, 0x80, 0x80, 0x00, 0x22, 0x00, 0x0d, 0x00, + 0x41, 0x00, 0x0f, 0x0b, 0x41, 0x00, 0x20, 0x00, 0x36, 0x02, 0xac, 0x89, + 0x80, 0x80, 0x00, 0x41, 0x7f, 0x0b, 0x0d, 0x00, 0x20, 0x00, 0x28, 0x02, + 0x38, 0x10, 0x97, 0x80, 0x80, 0x80, 0x00, 0x0b, 0x71, 0x01, 0x02, 0x7f, + 0x23, 0x80, 0x80, 0x80, 0x80, 0x00, 0x41, 0x10, 0x6b, 0x22, 0x03, 0x24, + 0x80, 0x80, 0x80, 0x80, 0x00, 0x41, 0x7f, 0x21, 0x04, 0x02, 0x40, 0x02, + 0x40, 0x20, 0x02, 0x41, 0x7f, 0x4a, 0x0d, 0x00, 0x41, 0x00, 0x41, 0x1c, + 0x36, 0x02, 0xac, 0x89, 0x80, 0x80, 0x00, 0x0c, 0x01, 0x0b, 0x02, 0x40, + 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x20, 0x03, 0x41, 0x0c, 0x6a, 0x10, + 0x8b, 0x80, 0x80, 0x80, 0x00, 0x22, 0x02, 0x45, 0x0d, 0x00, 0x41, 0x00, + 0x20, 0x02, 0x36, 0x02, 0xac, 0x89, 0x80, 0x80, 0x00, 0x41, 0x7f, 0x21, + 0x04, 0x0c, 0x01, 0x0b, 0x20, 0x03, 0x28, 0x02, 0x0c, 0x21, 0x04, 0x0b, + 0x20, 0x03, 0x41, 0x10, 0x6a, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, + 0x04, 0x0b, 0xbb, 0x02, 0x01, 0x07, 0x7f, 0x23, 0x80, 0x80, 0x80, 0x80, + 0x00, 0x41, 0x10, 0x6b, 0x22, 0x03, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, + 0x20, 0x03, 0x20, 0x02, 0x36, 0x02, 0x0c, 0x20, 0x03, 0x20, 0x01, 0x36, + 0x02, 0x08, 0x20, 0x03, 0x20, 0x00, 0x28, 0x02, 0x18, 0x22, 0x01, 0x36, + 0x02, 0x00, 0x20, 0x03, 0x20, 0x00, 0x28, 0x02, 0x14, 0x20, 0x01, 0x6b, + 0x22, 0x04, 0x36, 0x02, 0x04, 0x41, 0x02, 0x21, 0x05, 0x02, 0x40, 0x02, + 0x40, 0x20, 0x00, 0x28, 0x02, 0x38, 0x20, 0x03, 0x41, 0x02, 0x10, 0x99, + 0x80, 0x80, 0x80, 0x00, 0x22, 0x01, 0x20, 0x04, 0x20, 0x02, 0x6a, 0x22, + 0x06, 0x46, 0x0d, 0x00, 0x20, 0x03, 0x21, 0x04, 0x03, 0x40, 0x02, 0x40, + 0x20, 0x01, 0x41, 0x7f, 0x4a, 0x0d, 0x00, 0x41, 0x00, 0x21, 0x01, 0x20, + 0x00, 0x41, 0x00, 0x36, 0x02, 0x18, 0x20, 0x00, 0x42, 0x00, 0x37, 0x03, + 0x10, 0x20, 0x00, 0x20, 0x00, 0x28, 0x02, 0x00, 0x41, 0x20, 0x72, 0x36, + 0x02, 0x00, 0x20, 0x05, 0x41, 0x02, 0x46, 0x0d, 0x03, 0x20, 0x02, 0x20, + 0x04, 0x28, 0x02, 0x04, 0x6b, 0x21, 0x01, 0x0c, 0x03, 0x0b, 0x20, 0x04, + 0x20, 0x01, 0x20, 0x04, 0x28, 0x02, 0x04, 0x22, 0x07, 0x4b, 0x22, 0x08, + 0x41, 0x03, 0x74, 0x6a, 0x22, 0x09, 0x20, 0x09, 0x28, 0x02, 0x00, 0x20, + 0x01, 0x20, 0x07, 0x41, 0x00, 0x20, 0x08, 0x1b, 0x6b, 0x22, 0x07, 0x6a, + 0x36, 0x02, 0x00, 0x20, 0x04, 0x41, 0x0c, 0x41, 0x04, 0x20, 0x08, 0x1b, + 0x6a, 0x22, 0x04, 0x20, 0x04, 0x28, 0x02, 0x00, 0x20, 0x07, 0x6b, 0x36, + 0x02, 0x00, 0x20, 0x09, 0x21, 0x04, 0x20, 0x06, 0x20, 0x01, 0x6b, 0x22, + 0x06, 0x20, 0x00, 0x28, 0x02, 0x38, 0x20, 0x09, 0x20, 0x05, 0x20, 0x08, + 0x6b, 0x22, 0x05, 0x10, 0x99, 0x80, 0x80, 0x80, 0x00, 0x22, 0x01, 0x47, + 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x00, 0x20, 0x00, 0x28, 0x02, 0x28, 0x22, + 0x01, 0x36, 0x02, 0x18, 0x20, 0x00, 0x20, 0x01, 0x36, 0x02, 0x14, 0x20, + 0x00, 0x20, 0x01, 0x20, 0x00, 0x28, 0x02, 0x2c, 0x6a, 0x36, 0x02, 0x10, + 0x20, 0x02, 0x21, 0x01, 0x0b, 0x20, 0x03, 0x41, 0x10, 0x6a, 0x24, 0x80, + 0x80, 0x80, 0x80, 0x00, 0x20, 0x01, 0x0b, 0x66, 0x01, 0x02, 0x7f, 0x23, + 0x80, 0x80, 0x80, 0x80, 0x00, 0x41, 0x20, 0x6b, 0x22, 0x01, 0x24, 0x80, + 0x80, 0x80, 0x80, 0x00, 0x02, 0x40, 0x02, 0x40, 0x20, 0x00, 0x20, 0x01, + 0x41, 0x08, 0x6a, 0x10, 0x89, 0x80, 0x80, 0x80, 0x00, 0x22, 0x00, 0x0d, + 0x00, 0x41, 0x3b, 0x21, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x08, 0x41, 0x02, + 0x47, 0x0d, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x10, 0x41, 0x24, 0x71, 0x0d, + 0x00, 0x41, 0x01, 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x41, 0x00, 0x21, 0x02, + 0x41, 0x00, 0x20, 0x00, 0x36, 0x02, 0xac, 0x89, 0x80, 0x80, 0x00, 0x0b, + 0x20, 0x01, 0x41, 0x20, 0x6a, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, + 0x02, 0x0b, 0x3b, 0x00, 0x20, 0x00, 0x41, 0x81, 0x80, 0x80, 0x80, 0x00, + 0x36, 0x02, 0x20, 0x02, 0x40, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x41, 0xc0, + 0x00, 0x71, 0x0d, 0x00, 0x20, 0x00, 0x28, 0x02, 0x38, 0x10, 0x9b, 0x80, + 0x80, 0x80, 0x00, 0x0d, 0x00, 0x20, 0x00, 0x41, 0x7f, 0x36, 0x02, 0x40, + 0x0b, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x10, 0x9a, 0x80, 0x80, 0x80, + 0x00, 0x0b, 0x64, 0x01, 0x01, 0x7f, 0x23, 0x80, 0x80, 0x80, 0x80, 0x00, + 0x41, 0x10, 0x6b, 0x22, 0x03, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, 0x02, + 0x40, 0x02, 0x40, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x41, 0xff, 0x01, + 0x71, 0x20, 0x03, 0x41, 0x08, 0x6a, 0x10, 0x8a, 0x80, 0x80, 0x80, 0x00, + 0x22, 0x02, 0x45, 0x0d, 0x00, 0x41, 0x00, 0x41, 0xc6, 0x00, 0x20, 0x02, + 0x20, 0x02, 0x41, 0xcc, 0x00, 0x46, 0x1b, 0x36, 0x02, 0xac, 0x89, 0x80, + 0x80, 0x00, 0x42, 0x7f, 0x21, 0x01, 0x0c, 0x01, 0x0b, 0x20, 0x03, 0x29, + 0x03, 0x08, 0x21, 0x01, 0x0b, 0x20, 0x03, 0x41, 0x10, 0x6a, 0x24, 0x80, + 0x80, 0x80, 0x80, 0x00, 0x20, 0x01, 0x0b, 0x11, 0x00, 0x20, 0x00, 0x28, + 0x02, 0x38, 0x20, 0x01, 0x20, 0x02, 0x10, 0x9d, 0x80, 0x80, 0x80, 0x00, + 0x0b, 0xee, 0x07, 0x01, 0x04, 0x7f, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, + 0x20, 0x02, 0x41, 0x20, 0x4b, 0x0d, 0x00, 0x20, 0x01, 0x41, 0x03, 0x71, + 0x45, 0x0d, 0x01, 0x20, 0x02, 0x45, 0x0d, 0x01, 0x20, 0x00, 0x20, 0x01, + 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x02, 0x41, 0x7f, 0x6a, 0x21, + 0x03, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x21, 0x04, 0x20, 0x01, 0x41, 0x01, + 0x6a, 0x22, 0x05, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x02, 0x20, 0x03, 0x45, + 0x0d, 0x02, 0x20, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x01, 0x3a, 0x00, 0x01, + 0x20, 0x02, 0x41, 0x7e, 0x6a, 0x21, 0x03, 0x20, 0x00, 0x41, 0x02, 0x6a, + 0x21, 0x04, 0x20, 0x01, 0x41, 0x02, 0x6a, 0x22, 0x05, 0x41, 0x03, 0x71, + 0x45, 0x0d, 0x02, 0x20, 0x03, 0x45, 0x0d, 0x02, 0x20, 0x00, 0x20, 0x01, + 0x2d, 0x00, 0x02, 0x3a, 0x00, 0x02, 0x20, 0x02, 0x41, 0x7d, 0x6a, 0x21, + 0x03, 0x20, 0x00, 0x41, 0x03, 0x6a, 0x21, 0x04, 0x20, 0x01, 0x41, 0x03, + 0x6a, 0x22, 0x05, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x02, 0x20, 0x03, 0x45, + 0x0d, 0x02, 0x20, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x03, 0x3a, 0x00, 0x03, + 0x20, 0x02, 0x41, 0x7c, 0x6a, 0x21, 0x03, 0x20, 0x00, 0x41, 0x04, 0x6a, + 0x21, 0x04, 0x20, 0x01, 0x41, 0x04, 0x6a, 0x21, 0x05, 0x0c, 0x02, 0x0b, + 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0xfc, 0x0a, 0x00, 0x00, 0x20, 0x00, + 0x0f, 0x0b, 0x20, 0x02, 0x21, 0x03, 0x20, 0x00, 0x21, 0x04, 0x20, 0x01, + 0x21, 0x05, 0x0b, 0x02, 0x40, 0x02, 0x40, 0x20, 0x04, 0x41, 0x03, 0x71, + 0x22, 0x02, 0x0d, 0x00, 0x02, 0x40, 0x02, 0x40, 0x20, 0x03, 0x41, 0x10, + 0x4f, 0x0d, 0x00, 0x20, 0x03, 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x02, 0x40, + 0x20, 0x03, 0x41, 0x70, 0x6a, 0x22, 0x02, 0x41, 0x10, 0x71, 0x0d, 0x00, + 0x20, 0x04, 0x20, 0x05, 0x29, 0x02, 0x00, 0x37, 0x02, 0x00, 0x20, 0x04, + 0x20, 0x05, 0x29, 0x02, 0x08, 0x37, 0x02, 0x08, 0x20, 0x04, 0x41, 0x10, + 0x6a, 0x21, 0x04, 0x20, 0x05, 0x41, 0x10, 0x6a, 0x21, 0x05, 0x20, 0x02, + 0x21, 0x03, 0x0b, 0x20, 0x02, 0x41, 0x10, 0x49, 0x0d, 0x00, 0x20, 0x03, + 0x21, 0x02, 0x03, 0x40, 0x20, 0x04, 0x20, 0x05, 0x29, 0x02, 0x00, 0x37, + 0x02, 0x00, 0x20, 0x04, 0x20, 0x05, 0x29, 0x02, 0x08, 0x37, 0x02, 0x08, + 0x20, 0x04, 0x20, 0x05, 0x29, 0x02, 0x10, 0x37, 0x02, 0x10, 0x20, 0x04, + 0x20, 0x05, 0x29, 0x02, 0x18, 0x37, 0x02, 0x18, 0x20, 0x04, 0x41, 0x20, + 0x6a, 0x21, 0x04, 0x20, 0x05, 0x41, 0x20, 0x6a, 0x21, 0x05, 0x20, 0x02, + 0x41, 0x60, 0x6a, 0x22, 0x02, 0x41, 0x0f, 0x4b, 0x0d, 0x00, 0x0b, 0x0b, + 0x02, 0x40, 0x20, 0x02, 0x41, 0x08, 0x49, 0x0d, 0x00, 0x20, 0x04, 0x20, + 0x05, 0x29, 0x02, 0x00, 0x37, 0x02, 0x00, 0x20, 0x05, 0x41, 0x08, 0x6a, + 0x21, 0x05, 0x20, 0x04, 0x41, 0x08, 0x6a, 0x21, 0x04, 0x0b, 0x02, 0x40, + 0x20, 0x02, 0x41, 0x04, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x04, 0x20, 0x05, + 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, 0x20, 0x05, 0x41, 0x04, 0x6a, 0x21, + 0x05, 0x20, 0x04, 0x41, 0x04, 0x6a, 0x21, 0x04, 0x0b, 0x02, 0x40, 0x20, + 0x02, 0x41, 0x02, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x04, 0x20, 0x05, 0x2f, + 0x00, 0x00, 0x3b, 0x00, 0x00, 0x20, 0x04, 0x41, 0x02, 0x6a, 0x21, 0x04, + 0x20, 0x05, 0x41, 0x02, 0x6a, 0x21, 0x05, 0x0b, 0x20, 0x02, 0x41, 0x01, + 0x71, 0x45, 0x0d, 0x01, 0x20, 0x04, 0x20, 0x05, 0x2d, 0x00, 0x00, 0x3a, + 0x00, 0x00, 0x20, 0x00, 0x0f, 0x0b, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, + 0x02, 0x40, 0x02, 0x40, 0x20, 0x03, 0x41, 0x20, 0x49, 0x0d, 0x00, 0x20, + 0x04, 0x20, 0x05, 0x28, 0x02, 0x00, 0x22, 0x03, 0x3a, 0x00, 0x00, 0x02, + 0x40, 0x02, 0x40, 0x20, 0x02, 0x41, 0x7f, 0x6a, 0x0e, 0x03, 0x03, 0x00, + 0x01, 0x03, 0x0b, 0x20, 0x04, 0x20, 0x03, 0x41, 0x08, 0x76, 0x3a, 0x00, + 0x01, 0x20, 0x04, 0x20, 0x05, 0x41, 0x06, 0x6a, 0x29, 0x01, 0x00, 0x37, + 0x02, 0x06, 0x20, 0x04, 0x20, 0x05, 0x28, 0x02, 0x04, 0x41, 0x10, 0x74, + 0x20, 0x03, 0x41, 0x10, 0x76, 0x72, 0x36, 0x02, 0x02, 0x20, 0x04, 0x41, + 0x12, 0x6a, 0x21, 0x02, 0x20, 0x05, 0x41, 0x12, 0x6a, 0x21, 0x01, 0x41, + 0x0e, 0x21, 0x06, 0x20, 0x05, 0x41, 0x0e, 0x6a, 0x28, 0x01, 0x00, 0x21, + 0x05, 0x41, 0x0e, 0x21, 0x03, 0x0c, 0x03, 0x0b, 0x20, 0x04, 0x20, 0x05, + 0x41, 0x05, 0x6a, 0x29, 0x00, 0x00, 0x37, 0x02, 0x05, 0x20, 0x04, 0x20, + 0x05, 0x28, 0x02, 0x04, 0x41, 0x18, 0x74, 0x20, 0x03, 0x41, 0x08, 0x76, + 0x72, 0x36, 0x02, 0x01, 0x20, 0x04, 0x41, 0x11, 0x6a, 0x21, 0x02, 0x20, + 0x05, 0x41, 0x11, 0x6a, 0x21, 0x01, 0x41, 0x0d, 0x21, 0x06, 0x20, 0x05, + 0x41, 0x0d, 0x6a, 0x28, 0x00, 0x00, 0x21, 0x05, 0x41, 0x0f, 0x21, 0x03, + 0x0c, 0x02, 0x0b, 0x02, 0x40, 0x02, 0x40, 0x20, 0x03, 0x41, 0x10, 0x4f, + 0x0d, 0x00, 0x20, 0x04, 0x21, 0x02, 0x20, 0x05, 0x21, 0x01, 0x0c, 0x01, + 0x0b, 0x20, 0x04, 0x20, 0x05, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x20, + 0x04, 0x20, 0x05, 0x28, 0x00, 0x01, 0x36, 0x00, 0x01, 0x20, 0x04, 0x20, + 0x05, 0x29, 0x00, 0x05, 0x37, 0x00, 0x05, 0x20, 0x04, 0x20, 0x05, 0x2f, + 0x00, 0x0d, 0x3b, 0x00, 0x0d, 0x20, 0x04, 0x20, 0x05, 0x2d, 0x00, 0x0f, + 0x3a, 0x00, 0x0f, 0x20, 0x04, 0x41, 0x10, 0x6a, 0x21, 0x02, 0x20, 0x05, + 0x41, 0x10, 0x6a, 0x21, 0x01, 0x0b, 0x20, 0x03, 0x41, 0x08, 0x71, 0x0d, + 0x02, 0x0c, 0x03, 0x0b, 0x20, 0x04, 0x20, 0x03, 0x41, 0x10, 0x76, 0x3a, + 0x00, 0x02, 0x20, 0x04, 0x20, 0x03, 0x41, 0x08, 0x76, 0x3a, 0x00, 0x01, + 0x20, 0x04, 0x20, 0x05, 0x41, 0x07, 0x6a, 0x29, 0x00, 0x00, 0x37, 0x02, + 0x07, 0x20, 0x04, 0x20, 0x05, 0x28, 0x02, 0x04, 0x41, 0x08, 0x74, 0x20, + 0x03, 0x41, 0x18, 0x76, 0x72, 0x36, 0x02, 0x03, 0x20, 0x04, 0x41, 0x13, + 0x6a, 0x21, 0x02, 0x20, 0x05, 0x41, 0x13, 0x6a, 0x21, 0x01, 0x41, 0x0f, + 0x21, 0x06, 0x20, 0x05, 0x41, 0x0f, 0x6a, 0x28, 0x00, 0x00, 0x21, 0x05, + 0x41, 0x0d, 0x21, 0x03, 0x0b, 0x20, 0x04, 0x20, 0x06, 0x6a, 0x20, 0x05, + 0x36, 0x02, 0x00, 0x0b, 0x20, 0x02, 0x20, 0x01, 0x29, 0x00, 0x00, 0x37, + 0x00, 0x00, 0x20, 0x02, 0x41, 0x08, 0x6a, 0x21, 0x02, 0x20, 0x01, 0x41, + 0x08, 0x6a, 0x21, 0x01, 0x0b, 0x02, 0x40, 0x20, 0x03, 0x41, 0x04, 0x71, + 0x45, 0x0d, 0x00, 0x20, 0x02, 0x20, 0x01, 0x28, 0x00, 0x00, 0x36, 0x00, + 0x00, 0x20, 0x02, 0x41, 0x04, 0x6a, 0x21, 0x02, 0x20, 0x01, 0x41, 0x04, + 0x6a, 0x21, 0x01, 0x0b, 0x02, 0x40, 0x20, 0x03, 0x41, 0x02, 0x71, 0x45, + 0x0d, 0x00, 0x20, 0x02, 0x20, 0x01, 0x2f, 0x00, 0x00, 0x3b, 0x00, 0x00, + 0x20, 0x02, 0x41, 0x02, 0x6a, 0x21, 0x02, 0x20, 0x01, 0x41, 0x02, 0x6a, + 0x21, 0x01, 0x0b, 0x20, 0x03, 0x41, 0x01, 0x71, 0x45, 0x0d, 0x00, 0x20, + 0x02, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x0b, 0x20, 0x00, + 0x0b, 0xcf, 0x01, 0x01, 0x03, 0x7f, 0x20, 0x00, 0x21, 0x01, 0x02, 0x40, + 0x02, 0x40, 0x20, 0x00, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x00, 0x02, 0x40, + 0x20, 0x00, 0x2d, 0x00, 0x00, 0x0d, 0x00, 0x20, 0x00, 0x20, 0x00, 0x6b, + 0x0f, 0x0b, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x22, 0x01, 0x41, 0x03, 0x71, + 0x45, 0x0d, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x45, 0x0d, 0x01, 0x20, + 0x00, 0x41, 0x02, 0x6a, 0x22, 0x01, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x00, + 0x20, 0x01, 0x2d, 0x00, 0x00, 0x45, 0x0d, 0x01, 0x20, 0x00, 0x41, 0x03, + 0x6a, 0x22, 0x01, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x01, 0x2d, + 0x00, 0x00, 0x45, 0x0d, 0x01, 0x20, 0x00, 0x41, 0x04, 0x6a, 0x22, 0x01, + 0x41, 0x03, 0x71, 0x0d, 0x01, 0x0b, 0x20, 0x01, 0x41, 0x7c, 0x6a, 0x21, + 0x02, 0x20, 0x01, 0x41, 0x7b, 0x6a, 0x21, 0x01, 0x03, 0x40, 0x20, 0x01, + 0x41, 0x04, 0x6a, 0x21, 0x01, 0x41, 0x80, 0x82, 0x84, 0x08, 0x20, 0x02, + 0x41, 0x04, 0x6a, 0x22, 0x02, 0x28, 0x02, 0x00, 0x22, 0x03, 0x6b, 0x20, + 0x03, 0x72, 0x41, 0x80, 0x81, 0x82, 0x84, 0x78, 0x71, 0x41, 0x80, 0x81, + 0x82, 0x84, 0x78, 0x46, 0x0d, 0x00, 0x0b, 0x03, 0x40, 0x20, 0x01, 0x41, + 0x01, 0x6a, 0x21, 0x01, 0x20, 0x02, 0x2d, 0x00, 0x00, 0x21, 0x03, 0x20, + 0x02, 0x41, 0x01, 0x6a, 0x21, 0x02, 0x20, 0x03, 0x0d, 0x00, 0x0b, 0x0b, + 0x20, 0x01, 0x20, 0x00, 0x6b, 0x0b, 0x0b, 0x9d, 0x01, 0x02, 0x00, 0x41, + 0x80, 0x08, 0x0b, 0x1c, 0x0a, 0x0a, 0x09, 0x48, 0x65, 0x6c, 0x6c, 0x6f, + 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, + 0x4f, 0x63, 0x72, 0x65, 0x21, 0x0a, 0x0a, 0x00, 0x00, 0x41, 0xa0, 0x08, + 0x0b, 0x74, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xb8, 0x04, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00 + }; static const unsigned int wasm_binary_len = 3850; diff --git a/src/ocre/ocre_messaging/ocre_messaging.c b/src/ocre/ocre_messaging/ocre_messaging.c index 4d68a71f..29cfe5c2 100644 --- a/src/ocre/ocre_messaging/ocre_messaging.c +++ b/src/ocre/ocre_messaging/ocre_messaging.c @@ -20,263 +20,255 @@ LOG_MODULE_DECLARE(ocre_cs_component, OCRE_LOG_LEVEL); /* Messaging subscription structure */ typedef struct { - char topic[OCRE_MAX_TOPIC_LEN]; - wasm_module_inst_t module_inst; - bool is_active; + char topic[OCRE_MAX_TOPIC_LEN]; + wasm_module_inst_t module_inst; + bool is_active; } ocre_messaging_subscription_t; typedef struct { - ocre_messaging_subscription_t subscriptions[CONFIG_MESSAGING_MAX_SUBSCRIPTIONS]; - uint16_t subscription_count; - core_mutex_t mutex; + ocre_messaging_subscription_t subscriptions[CONFIG_MESSAGING_MAX_SUBSCRIPTIONS]; + uint16_t subscription_count; + core_mutex_t mutex; } ocre_messaging_system_t; static ocre_messaging_system_t messaging_system = {0}; static bool messaging_system_initialized = false; /* Initialize messaging system */ -int ocre_messaging_init(void) -{ - if (messaging_system_initialized) { - LOG_INF("Messaging system already initialized"); - return 0; - } - - if (!common_initialized && ocre_common_init() != 0) { - LOG_ERR("Failed to initialize common subsystem"); - return -EAGAIN; - } - - memset(&messaging_system, 0, sizeof(ocre_messaging_system_t)); - - core_mutex_init(&messaging_system.mutex); - - ocre_register_cleanup_handler(OCRE_RESOURCE_TYPE_MESSAGING, ocre_messaging_cleanup_container); - messaging_system_initialized = true; - LOG_INF("Messaging system initialized"); - return 0; +int ocre_messaging_init(void) { + if (messaging_system_initialized) { + LOG_INF("Messaging system already initialized"); + return 0; + } + + if (!common_initialized && ocre_common_init() != 0) { + LOG_ERR("Failed to initialize common subsystem"); + return -EAGAIN; + } + + memset(&messaging_system, 0, sizeof(ocre_messaging_system_t)); + + core_mutex_init(&messaging_system.mutex); + + ocre_register_cleanup_handler(OCRE_RESOURCE_TYPE_MESSAGING, ocre_messaging_cleanup_container); + messaging_system_initialized = true; + LOG_INF("Messaging system initialized"); + return 0; } /* Cleanup messaging resources for a module */ -void ocre_messaging_cleanup_container(wasm_module_inst_t module_inst) -{ - if (!messaging_system_initialized || !module_inst) { - return; - } - - core_mutex_lock(&messaging_system.mutex); - - for (int i = 0; i < CONFIG_MESSAGING_MAX_SUBSCRIPTIONS; i++) { - if (messaging_system.subscriptions[i].is_active && - messaging_system.subscriptions[i].module_inst == module_inst) { - messaging_system.subscriptions[i].is_active = false; - messaging_system.subscriptions[i].module_inst = NULL; - messaging_system.subscriptions[i].topic[0] = '\0'; - messaging_system.subscription_count--; - ocre_decrement_resource_count(module_inst, OCRE_RESOURCE_TYPE_MESSAGING); - LOG_DBG("Cleaned up subscription %d for module %p", i, (void *)module_inst); - } - } - - core_mutex_unlock(&messaging_system.mutex); - - LOG_DBG("Cleaned up messaging resources for module %p", (void *)module_inst); +void ocre_messaging_cleanup_container(wasm_module_inst_t module_inst) { + if (!messaging_system_initialized || !module_inst) { + return; + } + + core_mutex_lock(&messaging_system.mutex); + + for (int i = 0; i < CONFIG_MESSAGING_MAX_SUBSCRIPTIONS; i++) { + if (messaging_system.subscriptions[i].is_active && + messaging_system.subscriptions[i].module_inst == module_inst) { + messaging_system.subscriptions[i].is_active = false; + messaging_system.subscriptions[i].module_inst = NULL; + messaging_system.subscriptions[i].topic[0] = '\0'; + messaging_system.subscription_count--; + ocre_decrement_resource_count(module_inst, OCRE_RESOURCE_TYPE_MESSAGING); + LOG_DBG("Cleaned up subscription %d for module %p", i, (void *)module_inst); + } + } + + core_mutex_unlock(&messaging_system.mutex); + + LOG_DBG("Cleaned up messaging resources for module %p", (void *)module_inst); } /* Subscribe to a topic */ -int ocre_messaging_subscribe(wasm_exec_env_t exec_env, void *topic) -{ - if (!messaging_system_initialized) { - if (ocre_messaging_init() != 0) { - LOG_ERR("Failed to initialize messaging system"); - return -EINVAL; - } - } - - if (!topic || ((char *)topic)[0] == '\0') { - LOG_ERR("Topic is NULL or empty"); - return -EINVAL; - } - - wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); - if (!module_inst) { - LOG_ERR("No module instance for exec_env"); - return -EINVAL; - } - - ocre_module_context_t *ctx = ocre_get_module_context(module_inst); - if (!ctx) { - LOG_ERR("Module context not found for module instance %p", (void *)module_inst); - return -EINVAL; - } - - core_mutex_lock(&messaging_system.mutex); - - // Check if already subscribed - for (int i = 0; i < CONFIG_MESSAGING_MAX_SUBSCRIPTIONS; i++) { - if (messaging_system.subscriptions[i].is_active && - messaging_system.subscriptions[i].module_inst == module_inst && - strcmp(messaging_system.subscriptions[i].topic, (char *)topic) == 0) { - LOG_INF("Already subscribed to topic: %s", (char *)topic); - core_mutex_unlock(&messaging_system.mutex); - return 0; - } - } - - // Find a free slot - for (int i = 0; i < CONFIG_MESSAGING_MAX_SUBSCRIPTIONS; i++) { - if (!messaging_system.subscriptions[i].is_active) { - strncpy(messaging_system.subscriptions[i].topic, (char *)topic, OCRE_MAX_TOPIC_LEN - 1); - messaging_system.subscriptions[i].topic[OCRE_MAX_TOPIC_LEN - 1] = '\0'; - messaging_system.subscriptions[i].module_inst = module_inst; - messaging_system.subscriptions[i].is_active = true; - messaging_system.subscription_count++; - ocre_increment_resource_count(module_inst, OCRE_RESOURCE_TYPE_MESSAGING); - LOG_INF("Subscribed to topic: %s, module: %p", (char *)topic, (void *)module_inst); - core_mutex_unlock(&messaging_system.mutex); - return 0; - } - } - - core_mutex_unlock(&messaging_system.mutex); - - LOG_ERR("No free subscription slots available"); - return -ENOMEM; +int ocre_messaging_subscribe(wasm_exec_env_t exec_env, void *topic) { + if (!messaging_system_initialized) { + if (ocre_messaging_init() != 0) { + LOG_ERR("Failed to initialize messaging system"); + return -EINVAL; + } + } + + if (!topic || ((char *)topic)[0] == '\0') { + LOG_ERR("Topic is NULL or empty"); + return -EINVAL; + } + + wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); + if (!module_inst) { + LOG_ERR("No module instance for exec_env"); + return -EINVAL; + } + + ocre_module_context_t *ctx = ocre_get_module_context(module_inst); + if (!ctx) { + LOG_ERR("Module context not found for module instance %p", (void *)module_inst); + return -EINVAL; + } + + core_mutex_lock(&messaging_system.mutex); + + // Check if already subscribed + for (int i = 0; i < CONFIG_MESSAGING_MAX_SUBSCRIPTIONS; i++) { + if (messaging_system.subscriptions[i].is_active && + messaging_system.subscriptions[i].module_inst == module_inst && + strcmp(messaging_system.subscriptions[i].topic, (char *)topic) == 0) { + LOG_INF("Already subscribed to topic: %s", (char *)topic); + core_mutex_unlock(&messaging_system.mutex); + return 0; + } + } + + // Find a free slot + for (int i = 0; i < CONFIG_MESSAGING_MAX_SUBSCRIPTIONS; i++) { + if (!messaging_system.subscriptions[i].is_active) { + strncpy(messaging_system.subscriptions[i].topic, (char *)topic, OCRE_MAX_TOPIC_LEN - 1); + messaging_system.subscriptions[i].topic[OCRE_MAX_TOPIC_LEN - 1] = '\0'; + messaging_system.subscriptions[i].module_inst = module_inst; + messaging_system.subscriptions[i].is_active = true; + messaging_system.subscription_count++; + ocre_increment_resource_count(module_inst, OCRE_RESOURCE_TYPE_MESSAGING); + LOG_INF("Subscribed to topic: %s, module: %p", (char *)topic, (void *)module_inst); + core_mutex_unlock(&messaging_system.mutex); + return 0; + } + } + + core_mutex_unlock(&messaging_system.mutex); + + LOG_ERR("No free subscription slots available"); + return -ENOMEM; } /* Publish a message */ -int ocre_messaging_publish(wasm_exec_env_t exec_env, void *topic, void *content_type, void *payload, int payload_len) -{ - if (!messaging_system_initialized) { - if (ocre_messaging_init() != 0) { - LOG_ERR("Failed to initialize messaging system"); - return -EINVAL; - } - } - - if (!topic || ((char *)topic)[0] == '\0') { - LOG_ERR("Topic is NULL or empty"); - return -EINVAL; - } - if (!content_type || ((char *)content_type)[0] == '\0') { - LOG_ERR("Content type is NULL or empty"); - return -EINVAL; - } - if (!payload || payload_len <= 0) { - LOG_ERR("Payload is NULL or payload_len is invalid"); - return -EINVAL; - } - - wasm_module_inst_t publisher_module = wasm_runtime_get_module_inst(exec_env); - if (!publisher_module) { - LOG_ERR("No module instance for exec_env"); - return -EINVAL; - } - - static uint32_t message_id = 0; - bool message_sent = false; - - core_mutex_lock(&messaging_system.mutex); - - // Find matching subscriptions - for (int i = 0; i < CONFIG_MESSAGING_MAX_SUBSCRIPTIONS; i++) { - if (!messaging_system.subscriptions[i].is_active) { - continue; - } - - // Check if the published topic matches the subscription (prefix match) - const char *subscribed_topic = messaging_system.subscriptions[i].topic; - size_t subscribed_len = strlen(subscribed_topic); - - if (strncmp(subscribed_topic, (char *)topic, subscribed_len) != 0) { - continue; // No prefix match - } - - wasm_module_inst_t target_module = messaging_system.subscriptions[i].module_inst; - if (!target_module) { - LOG_ERR("Invalid module instance for subscription %d", i); - continue; - } - - // Allocate WASM memory for the target module - uint32_t topic_offset = - (uint32_t)wasm_runtime_module_dup_data(target_module, (char *)topic, strlen((char *)topic) + 1); - if (topic_offset == 0) { - LOG_ERR("Failed to allocate WASM memory for topic"); - continue; - } - - uint32_t content_offset = (uint32_t)wasm_runtime_module_dup_data(target_module, (char *)content_type, - strlen((char *)content_type) + 1); - if (content_offset == 0) { - LOG_ERR("Failed to allocate WASM memory for content_type"); - wasm_runtime_module_free(target_module, topic_offset); - continue; - } - - uint32_t payload_offset = (uint32_t)wasm_runtime_module_dup_data(target_module, payload, payload_len); - if (payload_offset == 0) { - LOG_ERR("Failed to allocate WASM memory for payload"); - wasm_runtime_module_free(target_module, topic_offset); - wasm_runtime_module_free(target_module, content_offset); - continue; - } - - // Create and queue the messaging event - ocre_event_t event; - event.type = OCRE_RESOURCE_TYPE_MESSAGING; - event.data.messaging_event.message_id = message_id; - event.data.messaging_event.topic = topic; - event.data.messaging_event.topic_offset = topic_offset; - event.data.messaging_event.content_type = content_type; - event.data.messaging_event.content_type_offset = content_offset; - event.data.messaging_event.payload = payload; - event.data.messaging_event.payload_offset = payload_offset; - event.data.messaging_event.payload_len = (uint32_t)payload_len; - event.owner = target_module; - - LOG_DBG("Creating messaging event: ID=%d, topic=%s, content_type=%s, payload_len=%d for module %p", - message_id, (char *)topic, (char *)content_type, payload_len, (void *)target_module); - - core_spinlock_key_t key = core_spinlock_lock(&ocre_event_queue_lock); - if (core_eventq_put(&ocre_event_queue, &event) != 0) { - LOG_ERR("Failed to queue messaging event for message ID %d", message_id); - wasm_runtime_module_free(target_module, topic_offset); - wasm_runtime_module_free(target_module, content_offset); - wasm_runtime_module_free(target_module, payload_offset); - } else { - message_sent = true; - LOG_DBG("Queued messaging event for message ID %d", message_id); - } - core_spinlock_unlock(&ocre_event_queue_lock, key); - } - - core_mutex_unlock(&messaging_system.mutex); - - if (message_sent) { - LOG_DBG("Published message: ID=%d, topic=%s, content_type=%s, payload_len=%d", message_id, - (char *)topic, (char *)content_type, payload_len); - message_id++; - return 0; - } else { - LOG_WRN("No matching subscriptions found for topic %s", (char *)topic); - return -ENOENT; - } +int ocre_messaging_publish(wasm_exec_env_t exec_env, void *topic, void *content_type, void *payload, int payload_len) { + if (!messaging_system_initialized) { + if (ocre_messaging_init() != 0) { + LOG_ERR("Failed to initialize messaging system"); + return -EINVAL; + } + } + + if (!topic || ((char *)topic)[0] == '\0') { + LOG_ERR("Topic is NULL or empty"); + return -EINVAL; + } + if (!content_type || ((char *)content_type)[0] == '\0') { + LOG_ERR("Content type is NULL or empty"); + return -EINVAL; + } + if (!payload || payload_len <= 0) { + LOG_ERR("Payload is NULL or payload_len is invalid"); + return -EINVAL; + } + + wasm_module_inst_t publisher_module = wasm_runtime_get_module_inst(exec_env); + if (!publisher_module) { + LOG_ERR("No module instance for exec_env"); + return -EINVAL; + } + + static uint32_t message_id = 0; + bool message_sent = false; + + core_mutex_lock(&messaging_system.mutex); + + // Find matching subscriptions + for (int i = 0; i < CONFIG_MESSAGING_MAX_SUBSCRIPTIONS; i++) { + if (!messaging_system.subscriptions[i].is_active) { + continue; + } + + // Check if the published topic matches the subscription (prefix match) + const char *subscribed_topic = messaging_system.subscriptions[i].topic; + size_t subscribed_len = strlen(subscribed_topic); + + if (strncmp(subscribed_topic, (char *)topic, subscribed_len) != 0) { + continue; // No prefix match + } + + wasm_module_inst_t target_module = messaging_system.subscriptions[i].module_inst; + if (!target_module) { + LOG_ERR("Invalid module instance for subscription %d", i); + continue; + } + + // Allocate WASM memory for the target module + uint32_t topic_offset = (uint32_t)wasm_runtime_module_dup_data(target_module, (char *)topic, strlen((char *)topic) + 1); + if (topic_offset == 0) { + LOG_ERR("Failed to allocate WASM memory for topic"); + continue; + } + + uint32_t content_offset = (uint32_t)wasm_runtime_module_dup_data(target_module, (char *)content_type, strlen((char *)content_type) + 1); + if (content_offset == 0) { + LOG_ERR("Failed to allocate WASM memory for content_type"); + wasm_runtime_module_free(target_module, topic_offset); + continue; + } + + uint32_t payload_offset = (uint32_t)wasm_runtime_module_dup_data(target_module, payload, payload_len); + if (payload_offset == 0) { + LOG_ERR("Failed to allocate WASM memory for payload"); + wasm_runtime_module_free(target_module, topic_offset); + wasm_runtime_module_free(target_module, content_offset); + continue; + } + + // Create and queue the messaging event + ocre_event_t event; + event.type = OCRE_RESOURCE_TYPE_MESSAGING; + event.data.messaging_event.message_id = message_id; + event.data.messaging_event.topic = topic; + event.data.messaging_event.topic_offset = topic_offset; + event.data.messaging_event.content_type = content_type; + event.data.messaging_event.content_type_offset = content_offset; + event.data.messaging_event.payload = payload; + event.data.messaging_event.payload_offset = payload_offset; + event.data.messaging_event.payload_len = (uint32_t)payload_len; + event.owner = target_module; + + LOG_DBG("Creating messaging event: ID=%d, topic=%s, content_type=%s, payload_len=%d for module %p", + message_id, (char *)topic, (char *)content_type, payload_len, (void *)target_module); + + core_spinlock_key_t key = core_spinlock_lock(&ocre_event_queue_lock); + if (core_eventq_put(&ocre_event_queue, &event) != 0) { + LOG_ERR("Failed to queue messaging event for message ID %d", message_id); + wasm_runtime_module_free(target_module, topic_offset); + wasm_runtime_module_free(target_module, content_offset); + wasm_runtime_module_free(target_module, payload_offset); + } else { + message_sent = true; + LOG_DBG("Queued messaging event for message ID %d", message_id); + } + core_spinlock_unlock(&ocre_event_queue_lock, key); + } + + core_mutex_unlock(&messaging_system.mutex); + + if (message_sent) { + LOG_DBG("Published message: ID=%d, topic=%s, content_type=%s, payload_len=%d", + message_id, (char *)topic, (char *)content_type, payload_len); + message_id++; + return 0; + } else { + LOG_WRN("No matching subscriptions found for topic %s", (char *)topic); + return -ENOENT; + } } /* Free module event data */ -int ocre_messaging_free_module_event_data(wasm_exec_env_t exec_env, uint32_t topic_offset, uint32_t content_offset, - uint32_t payload_offset) -{ - wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); - if (!module_inst) { - LOG_ERR("Cannot find module_inst for free event data"); - return -EINVAL; - } - - wasm_runtime_module_free(module_inst, topic_offset); - wasm_runtime_module_free(module_inst, content_offset); - wasm_runtime_module_free(module_inst, payload_offset); - - return 0; +int ocre_messaging_free_module_event_data(wasm_exec_env_t exec_env, uint32_t topic_offset, uint32_t content_offset, uint32_t payload_offset) { + wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); + if (!module_inst) { + LOG_ERR("Cannot find module_inst for free event data"); + return -EINVAL; + } + + wasm_runtime_module_free(module_inst, topic_offset); + wasm_runtime_module_free(module_inst, content_offset); + wasm_runtime_module_free(module_inst, payload_offset); + + return 0; } diff --git a/src/ocre/ocre_messaging/ocre_messaging.h b/src/ocre/ocre_messaging/ocre_messaging.h index 9d74d1a2..d46eb56e 100644 --- a/src/ocre/ocre_messaging/ocre_messaging.h +++ b/src/ocre/ocre_messaging/ocre_messaging.h @@ -18,11 +18,11 @@ * @brief Structure representing an OCRE message. */ typedef struct { - uint32_t mid; ///< Message ID - void *topic; ///< Topic of the message (pointer to string) - void *content_type; ///< Content type (e.g., MIME type, pointer to string) - void *payload; ///< Message payload - uint32_t payload_len; ///< Length of the payload + uint32_t mid; ///< Message ID + void *topic; ///< Topic of the message (pointer to string) + void *content_type; ///< Content type (e.g., MIME type, pointer to string) + void *payload; ///< Message payload + uint32_t payload_len; ///< Length of the payload } ocre_msg_t; /** @@ -73,6 +73,6 @@ void ocre_messaging_cleanup_container(wasm_module_inst_t module_inst); * @return OCRE_SUCCESS on success, negative error code on failure. */ int ocre_messaging_free_module_event_data(wasm_exec_env_t exec_env, uint32_t topic_offset, uint32_t content_offset, - uint32_t payload_offset); + uint32_t payload_offset); #endif /* OCRE_MESSAGING_H */ diff --git a/src/ocre/ocre_sensors/ocre_sensors.c b/src/ocre/ocre_sensors/ocre_sensors.c index 3e1af8c1..e2d36dd8 100644 --- a/src/ocre/ocre_sensors/ocre_sensors.c +++ b/src/ocre/ocre_sensors/ocre_sensors.c @@ -13,14 +13,14 @@ LOG_MODULE_DECLARE(ocre_sensors, OCRE_LOG_LEVEL); #include "ocre_sensors.h" -#define DEVICE_NODE DT_PATH(devices) +#define DEVICE_NODE DT_PATH(devices) #define HAS_DEVICE_NODES DT_NODE_EXISTS(DEVICE_NODE) && DT_PROP_LEN(DEVICE_NODE, device_list) > 1 /* Define sensor discovery names from device tree if available */ #if (CONFIG_OCRE_SENSORS) && (HAS_DEVICE_NODES) #define EXTRACT_LABELS(node_id, prop, idx) DT_PROP_BY_PHANDLE_IDX_OR(node_id, prop, idx, label, "undefined") static const char *sensor_discovery_names[] = { - DT_FOREACH_PROP_ELEM_SEP(DEVICE_NODE, device_list, EXTRACT_LABELS, (, ))}; + DT_FOREACH_PROP_ELEM_SEP(DEVICE_NODE, device_list, EXTRACT_LABELS, (, ))}; static int sensor_names_count = sizeof(sensor_discovery_names) / sizeof(sensor_discovery_names[0]); #else static const char *sensor_discovery_names[] = {}; @@ -28,282 +28,266 @@ static int sensor_names_count = 0; #endif typedef struct { - const struct device *device; - ocre_sensor_t info; - bool in_use; + const struct device *device; + ocre_sensor_t info; + bool in_use; } ocre_sensor_internal_t; static ocre_sensor_internal_t sensors[CONFIG_MAX_SENSORS] = {0}; static int sensor_count = 0; -static int set_opened_channels(const struct device *dev, enum sensor_channel *channels) -{ - if (!channels) { - LOG_ERR("Channels array is NULL"); - return -EINVAL; - } - - if (!device_is_ready(dev)) { - LOG_ERR("Device is not ready"); - return -ENODEV; - } - - if (sensor_sample_fetch(dev) < 0) { - LOG_WRN("Failed to fetch sensor data - sensor might not be initialized"); - } - - int count = 0; - struct sensor_value value = {}; - - for (int channel = 0; channel < SENSOR_CHAN_ALL && count < CONFIG_MAX_CHANNELS_PER_SENSOR; channel++) { - if (channel != SENSOR_CHAN_ACCEL_XYZ && channel != SENSOR_CHAN_GYRO_XYZ && - channel != SENSOR_CHAN_MAGN_XYZ && channel != SENSOR_CHAN_POS_DXYZ) { - if (sensor_channel_get(dev, channel, &value) == 0) { - channels[count] = channel; - count++; - } - } - } - return count; +static int set_opened_channels(const struct device *dev, enum sensor_channel *channels) { + if (!channels) { + LOG_ERR("Channels array is NULL"); + return -EINVAL; + } + + if (!device_is_ready(dev)) { + LOG_ERR("Device is not ready"); + return -ENODEV; + } + + if (sensor_sample_fetch(dev) < 0) { + LOG_WRN("Failed to fetch sensor data - sensor might not be initialized"); + } + + int count = 0; + struct sensor_value value = {}; + + for (int channel = 0; channel < SENSOR_CHAN_ALL && count < CONFIG_MAX_CHANNELS_PER_SENSOR; channel++) { + if (channel != SENSOR_CHAN_ACCEL_XYZ && channel != SENSOR_CHAN_GYRO_XYZ && channel != SENSOR_CHAN_MAGN_XYZ && + channel != SENSOR_CHAN_POS_DXYZ) { + if (sensor_channel_get(dev, channel, &value) == 0) { + channels[count] = channel; + count++; + } + } + } + return count; } -int ocre_sensors_init(wasm_exec_env_t exec_env) -{ - memset(sensors, 0, sizeof(sensors)); - sensor_count = 0; - return 0; +int ocre_sensors_init(wasm_exec_env_t exec_env) { + memset(sensors, 0, sizeof(sensors)); + sensor_count = 0; + return 0; } -int ocre_sensors_open(wasm_exec_env_t exec_env, ocre_sensor_handle_t handle) -{ - if (handle < 0 || handle >= sensor_count || !sensors[handle].in_use) { - LOG_ERR("Invalid sensor handle: %d", handle); - return -EINVAL; - } +int ocre_sensors_open(wasm_exec_env_t exec_env, ocre_sensor_handle_t handle) { + if (handle < 0 || handle >= sensor_count || !sensors[handle].in_use) { + LOG_ERR("Invalid sensor handle: %d", handle); + return -EINVAL; + } - if (!device_is_ready(sensors[handle].device)) { - LOG_ERR("Device %s is not ready", sensors[handle].info.sensor_name); - return -ENODEV; - } + if (!device_is_ready(sensors[handle].device)) { + LOG_ERR("Device %s is not ready", sensors[handle].info.sensor_name); + return -ENODEV; + } - return 0; + return 0; } -int ocre_sensors_discover(wasm_exec_env_t exec_env) -{ - memset(sensors, 0, sizeof(sensors)); - sensor_count = 0; - - const struct device *dev = NULL; - size_t device_count = z_device_get_all_static(&dev); - - if (!dev) { - LOG_ERR("Device list is NULL. Possible memory corruption!"); - return -EINVAL; - } - if (device_count == 0) { - LOG_ERR("No static devices found"); - return -ENODEV; - } - - LOG_INF("Total static devices found: %zu", device_count); - - for (size_t i = 0; i < device_count && sensor_count < CONFIG_MAX_SENSORS; i++) { - if (!dev[i].name) { - LOG_ERR("Device %zu has NULL name, skipping!", i); - continue; - } - - LOG_INF("Checking device: %s", dev[i].name); - - bool sensor_found = false; - for (int j = 0; j < sensor_names_count; j++) { - if (strcmp(dev[i].name, sensor_discovery_names[j]) == 0) { - sensor_found = true; - break; - } - } - if (!sensor_found) { - LOG_WRN("Skipping device, not in sensor list: %s", dev[i].name); - continue; - } - - const struct sensor_driver_api *api = (const struct sensor_driver_api *)dev[i].api; - if (!api || !api->channel_get) { - LOG_WRN("Device %s does not support sensor API or channel_get, skipping", dev[i].name); - continue; - } - - if (sensor_count >= CONFIG_MAX_SENSORS) { - LOG_WRN("Max sensor limit reached, skipping device: %s", dev[i].name); - continue; - } - - ocre_sensor_internal_t *sensor = &sensors[sensor_count]; - sensor->device = &dev[i]; - sensor->in_use = true; - sensor->info.handle = sensor_count; - - strncpy(sensor->info.sensor_name, dev[i].name, CONFIG_MAX_SENSOR_NAME_LENGTH - 1); - sensor->info.sensor_name[CONFIG_MAX_SENSOR_NAME_LENGTH - 1] = '\0'; - - sensor->info.num_channels = set_opened_channels(&dev[i], sensor->info.channels); - if (sensor->info.num_channels <= 0) { - LOG_WRN("Device %s does not have opened channels, skipping", dev[i].name); - continue; - } - - LOG_INF("Device has %d channels", sensor->info.num_channels); - sensor_count++; - } - - LOG_INF("Discovered %d sensors", sensor_count); - return sensor_count; +int ocre_sensors_discover(wasm_exec_env_t exec_env) { + memset(sensors, 0, sizeof(sensors)); + sensor_count = 0; + + const struct device *dev = NULL; + size_t device_count = z_device_get_all_static(&dev); + + if (!dev) { + LOG_ERR("Device list is NULL. Possible memory corruption!"); + return -EINVAL; + } + if (device_count == 0) { + LOG_ERR("No static devices found"); + return -ENODEV; + } + + LOG_INF("Total static devices found: %zu", device_count); + + for (size_t i = 0; i < device_count && sensor_count < CONFIG_MAX_SENSORS; i++) { + if (!dev[i].name) { + LOG_ERR("Device %zu has NULL name, skipping!", i); + continue; + } + + LOG_INF("Checking device: %s", dev[i].name); + + bool sensor_found = false; + for (int j = 0; j < sensor_names_count; j++) { + if (strcmp(dev[i].name, sensor_discovery_names[j]) == 0) { + sensor_found = true; + break; + } + } + if (!sensor_found) { + LOG_WRN("Skipping device, not in sensor list: %s", dev[i].name); + continue; + } + + const struct sensor_driver_api *api = (const struct sensor_driver_api *)dev[i].api; + if (!api || !api->channel_get) { + LOG_WRN("Device %s does not support sensor API or channel_get, skipping", dev[i].name); + continue; + } + + if (sensor_count >= CONFIG_MAX_SENSORS) { + LOG_WRN("Max sensor limit reached, skipping device: %s", dev[i].name); + continue; + } + + ocre_sensor_internal_t *sensor = &sensors[sensor_count]; + sensor->device = &dev[i]; + sensor->in_use = true; + sensor->info.handle = sensor_count; + + strncpy(sensor->info.sensor_name, dev[i].name, CONFIG_MAX_SENSOR_NAME_LENGTH - 1); + sensor->info.sensor_name[CONFIG_MAX_SENSOR_NAME_LENGTH - 1] = '\0'; + + sensor->info.num_channels = set_opened_channels(&dev[i], sensor->info.channels); + if (sensor->info.num_channels <= 0) { + LOG_WRN("Device %s does not have opened channels, skipping", dev[i].name); + continue; + } + + LOG_INF("Device has %d channels", sensor->info.num_channels); + sensor_count++; + } + + LOG_INF("Discovered %d sensors", sensor_count); + return sensor_count; } -int ocre_sensors_get_handle(wasm_exec_env_t exec_env, int sensor_id) -{ - if (sensor_id < 0 || sensor_id >= sensor_count || !sensors[sensor_id].in_use) { - return -EINVAL; - } - return sensors[sensor_id].info.handle; +int ocre_sensors_get_handle(wasm_exec_env_t exec_env, int sensor_id) { + if (sensor_id < 0 || sensor_id >= sensor_count || !sensors[sensor_id].in_use) { + return -EINVAL; + } + return sensors[sensor_id].info.handle; } -int ocre_sensors_get_name(wasm_exec_env_t exec_env, int sensor_id, char *buffer, int buffer_size) -{ - if (sensor_id < 0 || sensor_id >= sensor_count || !sensors[sensor_id].in_use || !buffer) { - return -EINVAL; - } +int ocre_sensors_get_name(wasm_exec_env_t exec_env, int sensor_id, char *buffer, int buffer_size) { + if (sensor_id < 0 || sensor_id >= sensor_count || !sensors[sensor_id].in_use || !buffer) { + return -EINVAL; + } - int name_len = strlen(sensors[sensor_id].info.sensor_name); - if (name_len >= buffer_size) { - return -ENOSPC; - } + int name_len = strlen(sensors[sensor_id].info.sensor_name); + if (name_len >= buffer_size) { + return -ENOSPC; + } - strncpy(buffer, sensors[sensor_id].info.sensor_name, buffer_size - 1); - buffer[buffer_size - 1] = '\0'; - return name_len; + strncpy(buffer, sensors[sensor_id].info.sensor_name, buffer_size - 1); + buffer[buffer_size - 1] = '\0'; + return name_len; } -int ocre_sensors_get_channel_count(wasm_exec_env_t exec_env, int sensor_id) -{ - if (sensor_id < 0 || sensor_id >= sensor_count || !sensors[sensor_id].in_use) { - return -EINVAL; - } - return sensors[sensor_id].info.num_channels; +int ocre_sensors_get_channel_count(wasm_exec_env_t exec_env, int sensor_id) { + if (sensor_id < 0 || sensor_id >= sensor_count || !sensors[sensor_id].in_use) { + return -EINVAL; + } + return sensors[sensor_id].info.num_channels; } -int ocre_sensors_get_channel_type(wasm_exec_env_t exec_env, int sensor_id, int channel_index) -{ - if (sensor_id < 0 || sensor_id >= sensor_count || !sensors[sensor_id].in_use || channel_index < 0 || - channel_index >= sensors[sensor_id].info.num_channels) { - return -EINVAL; - } - return sensors[sensor_id].info.channels[channel_index]; +int ocre_sensors_get_channel_type(wasm_exec_env_t exec_env, int sensor_id, int channel_index) { + if (sensor_id < 0 || sensor_id >= sensor_count || !sensors[sensor_id].in_use || channel_index < 0 || + channel_index >= sensors[sensor_id].info.num_channels) { + return -EINVAL; + } + return sensors[sensor_id].info.channels[channel_index]; } -double ocre_sensors_read(wasm_exec_env_t exec_env, int sensor_id, int channel_type) -{ - if (sensor_id < 0 || sensor_id >= sensor_count || !sensors[sensor_id].in_use) { - return -EINVAL; - } +double ocre_sensors_read(wasm_exec_env_t exec_env, int sensor_id, int channel_type) { + if (sensor_id < 0 || sensor_id >= sensor_count || !sensors[sensor_id].in_use) { + return -EINVAL; + } - const struct device *dev = sensors[sensor_id].device; - struct sensor_value value = {}; + const struct device *dev = sensors[sensor_id].device; + struct sensor_value value = {}; - if (sensor_sample_fetch(dev) < 0) { - LOG_ERR("Failed to fetch sensor data"); - return -EIO; - } + if (sensor_sample_fetch(dev) < 0) { + LOG_ERR("Failed to fetch sensor data"); + return -EIO; + } - if (sensor_channel_get(dev, channel_type, &value) < 0) { - LOG_ERR("Failed to get scalar channel data"); - return -EIO; - } + if (sensor_channel_get(dev, channel_type, &value) < 0) { + LOG_ERR("Failed to get scalar channel data"); + return -EIO; + } - return sensor_value_to_double(&value); + return sensor_value_to_double(&value); } -static int find_sensor_by_name(const char *name) -{ - if (!name) { - return -EINVAL; - } +static int find_sensor_by_name(const char *name) { + if (!name) { + return -EINVAL; + } - for (int i = 0; i < sensor_count; i++) { - if (sensors[i].in_use && strcmp(sensors[i].info.sensor_name, name) == 0) { - return i; - } - } + for (int i = 0; i < sensor_count; i++) { + if (sensors[i].in_use && strcmp(sensors[i].info.sensor_name, name) == 0) { + return i; + } + } - return -ENOENT; + return -ENOENT; } -int ocre_sensors_open_by_name(wasm_exec_env_t exec_env, const char *sensor_name) -{ - int sensor_id = find_sensor_by_name(sensor_name); - if (sensor_id < 0) { - LOG_ERR("Sensor not found: %s", sensor_name); - return -ENOENT; - } +int ocre_sensors_open_by_name(wasm_exec_env_t exec_env, const char *sensor_name) { + int sensor_id = find_sensor_by_name(sensor_name); + if (sensor_id < 0) { + LOG_ERR("Sensor not found: %s", sensor_name); + return -ENOENT; + } - return ocre_sensors_open(exec_env, sensor_id); + return ocre_sensors_open(exec_env, sensor_id); } -int ocre_sensors_get_handle_by_name(wasm_exec_env_t exec_env, const char *sensor_name) -{ - int sensor_id = find_sensor_by_name(sensor_name); - if (sensor_id < 0) { - return -ENOENT; - } +int ocre_sensors_get_handle_by_name(wasm_exec_env_t exec_env, const char *sensor_name) { + int sensor_id = find_sensor_by_name(sensor_name); + if (sensor_id < 0) { + return -ENOENT; + } - return sensors[sensor_id].info.handle; + return sensors[sensor_id].info.handle; } -int ocre_sensors_get_channel_count_by_name(wasm_exec_env_t exec_env, const char *sensor_name) -{ - int sensor_id = find_sensor_by_name(sensor_name); - if (sensor_id < 0) { - return -ENOENT; - } +int ocre_sensors_get_channel_count_by_name(wasm_exec_env_t exec_env, const char *sensor_name) { + int sensor_id = find_sensor_by_name(sensor_name); + if (sensor_id < 0) { + return -ENOENT; + } - return sensors[sensor_id].info.num_channels; + return sensors[sensor_id].info.num_channels; } -int ocre_sensors_get_channel_type_by_name(wasm_exec_env_t exec_env, const char *sensor_name, int channel_index) -{ - int sensor_id = find_sensor_by_name(sensor_name); - if (sensor_id < 0) { - return -ENOENT; - } +int ocre_sensors_get_channel_type_by_name(wasm_exec_env_t exec_env, const char *sensor_name, int channel_index) { + int sensor_id = find_sensor_by_name(sensor_name); + if (sensor_id < 0) { + return -ENOENT; + } - return ocre_sensors_get_channel_type(exec_env, sensor_id, channel_index); + return ocre_sensors_get_channel_type(exec_env, sensor_id, channel_index); } -double ocre_sensors_read_by_name(wasm_exec_env_t exec_env, const char *sensor_name, int channel_type) -{ - int sensor_id = find_sensor_by_name(sensor_name); - if (sensor_id < 0) { - LOG_ERR("Sensor not found: %s", sensor_name); - return -ENOENT; - } +double ocre_sensors_read_by_name(wasm_exec_env_t exec_env, const char *sensor_name, int channel_type) { + int sensor_id = find_sensor_by_name(sensor_name); + if (sensor_id < 0) { + LOG_ERR("Sensor not found: %s", sensor_name); + return -ENOENT; + } - return ocre_sensors_read(exec_env, sensor_id, channel_type); + return ocre_sensors_read(exec_env, sensor_id, channel_type); } -int ocre_sensors_get_list(wasm_exec_env_t exec_env, char **name_list, int max_names) -{ - if (!name_list || max_names <= 0) { - return -EINVAL; - } - - int count = 0; - for (int i = 0; i < sensor_count && count < max_names; i++) { - if (sensors[i].in_use) { - name_list[count] = (char *)sensors[i].info.sensor_name; - count++; - } - } - - return count; +int ocre_sensors_get_list(wasm_exec_env_t exec_env, char **name_list, int max_names) { + if (!name_list || max_names <= 0) { + return -EINVAL; + } + + int count = 0; + for (int i = 0; i < sensor_count && count < max_names; i++) { + if (sensors[i].in_use) { + name_list[count] = (char *)sensors[i].info.sensor_name; + count++; + } + } + + return count; } diff --git a/src/ocre/ocre_sensors/ocre_sensors.h b/src/ocre/ocre_sensors/ocre_sensors.h index 31059638..badad07b 100644 --- a/src/ocre/ocre_sensors/ocre_sensors.h +++ b/src/ocre/ocre_sensors/ocre_sensors.h @@ -19,25 +19,25 @@ typedef int32_t ocre_sensor_handle_t; * @brief Enum representing different sensor channels */ typedef enum { - SENSOR_CHANNEL_ACCELERATION, - SENSOR_CHANNEL_GYRO, - SENSOR_CHANNEL_MAGNETIC_FIELD, - SENSOR_CHANNEL_LIGHT, - SENSOR_CHANNEL_PRESSURE, - SENSOR_CHANNEL_PROXIMITY, - SENSOR_CHANNEL_HUMIDITY, - SENSOR_CHANNEL_TEMPERATURE, - // Add more channels as needed + SENSOR_CHANNEL_ACCELERATION, + SENSOR_CHANNEL_GYRO, + SENSOR_CHANNEL_MAGNETIC_FIELD, + SENSOR_CHANNEL_LIGHT, + SENSOR_CHANNEL_PRESSURE, + SENSOR_CHANNEL_PROXIMITY, + SENSOR_CHANNEL_HUMIDITY, + SENSOR_CHANNEL_TEMPERATURE, + // Add more channels as needed } sensor_channel_t; /** * @brief Structure representing a sensor instance */ typedef struct ocre_sensor_t { - ocre_sensor_handle_t handle; - char sensor_name[CONFIG_MAX_SENSOR_NAME_LENGTH]; - int num_channels; - enum sensor_channel channels[CONFIG_MAX_CHANNELS_PER_SENSOR]; + ocre_sensor_handle_t handle; + char sensor_name[CONFIG_MAX_SENSOR_NAME_LENGTH]; + int num_channels; + enum sensor_channel channels[CONFIG_MAX_CHANNELS_PER_SENSOR]; } ocre_sensor_t; /** * @brief Initialize the sensor system diff --git a/src/ocre/ocre_sensors/rng_sensor.c b/src/ocre/ocre_sensors/rng_sensor.c index 22acc6df..c172b59e 100644 --- a/src/ocre/ocre_sensors/rng_sensor.c +++ b/src/ocre/ocre_sensors/rng_sensor.c @@ -14,56 +14,53 @@ /* Define the sensor channels */ static enum sensor_channel rng_sensor_channels[] __attribute__((unused)) = { - SENSOR_CHAN_CUSTOM + 1, /* Define a custom channel */ + SENSOR_CHAN_CUSTOM + 1, /* Define a custom channel */ }; /* Define the sensor data structure */ struct rng_sensor_data { - struct sensor_value value; + struct sensor_value value; }; /* Define the sensor driver API functions */ /* Function to get sensor data */ -static int rng_sensor_sample_fetch(const struct device *dev, enum sensor_channel chan) -{ - struct rng_sensor_data *data = dev->data; +static int rng_sensor_sample_fetch(const struct device *dev, enum sensor_channel chan) { + struct rng_sensor_data *data = dev->data; - /* Generate a random 32-bit number */ - uint32_t random_number = sys_rand16_get(); + /* Generate a random 32-bit number */ + uint32_t random_number = sys_rand16_get(); - /* Store the random number in sensor_value */ - data->value.val1 = random_number; /* Integer part */ - data->value.val2 = 0; /* Fractional part */ + /* Store the random number in sensor_value */ + data->value.val1 = random_number; /* Integer part */ + data->value.val2 = 0; /* Fractional part */ - return 0; + return 0; } /* Function to retrieve sensor data */ -static int rng_sensor_channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) -{ - struct rng_sensor_data *data = dev->data; +static int rng_sensor_channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) { + struct rng_sensor_data *data = dev->data; - if (chan != SENSOR_CHAN_CUSTOM + 1) { - return -ENOTSUP; - } + if (chan != SENSOR_CHAN_CUSTOM + 1) { + return -ENOTSUP; + } - *val = data->value; + *val = data->value; - return 0; + return 0; } /* Define the sensor driver API */ static const struct sensor_driver_api rng_sensor_api = { - .sample_fetch = rng_sensor_sample_fetch, - .channel_get = rng_sensor_channel_get, + .sample_fetch = rng_sensor_sample_fetch, + .channel_get = rng_sensor_channel_get, }; /* Initialization function */ -int rng_sensor_init(const struct device *dev) -{ - /* Initialization code if needed */ - return 0; +int rng_sensor_init(const struct device *dev) { + /* Initialization code if needed */ + return 0; } // /* Define the sensor device */ @@ -71,5 +68,5 @@ int rng_sensor_init(const struct device *dev) static struct rng_sensor_data rng_sensor_data; DEVICE_DT_DEFINE(DT_DRV_INST(0), rng_sensor_init, NULL, &rng_sensor_data, NULL, POST_KERNEL, - CONFIG_SENSOR_INIT_PRIORITY, &rng_sensor_api); + CONFIG_SENSOR_INIT_PRIORITY, &rng_sensor_api); #endif diff --git a/src/ocre/ocre_timers/ocre_timer.c b/src/ocre/ocre_timers/ocre_timer.c index c1ce7b57..02a67d91 100644 --- a/src/ocre/ocre_timers/ocre_timer.c +++ b/src/ocre/ocre_timers/ocre_timer.c @@ -19,14 +19,14 @@ LOG_MODULE_DECLARE(ocre_cs_component, OCRE_LOG_LEVEL); /* Unified timer structure using core_timer API */ typedef struct { - uint32_t in_use : 1; - uint32_t id : 8; // Up to 256 timers - uint32_t interval : 16; // Up to 65s intervals - uint32_t periodic : 1; - uint32_t running : 1; // Track if timer is currently running - uint32_t start_time; // Start time for remaining time calculations - core_timer_t timer; // Unified core timer - wasm_module_inst_t owner; + uint32_t in_use: 1; + uint32_t id: 8; // Up to 256 timers + uint32_t interval: 16; // Up to 65s intervals + uint32_t periodic: 1; + uint32_t running: 1; // Track if timer is currently running + uint32_t start_time; // Start time for remaining time calculations + core_timer_t timer; // Unified core timer + wasm_module_inst_t owner; } ocre_timer_internal; #ifndef CONFIG_MAX_TIMERS @@ -39,225 +39,217 @@ static bool timer_system_initialized = false; static void unified_timer_callback(void *user_data); -void ocre_timer_init(void) -{ - if (timer_system_initialized) { - LOG_INF("Timer system already initialized"); - return; - } +void ocre_timer_init(void) { + if (timer_system_initialized) { + LOG_INF("Timer system already initialized"); + return; + } - if (!common_initialized && ocre_common_init() != 0) { - LOG_ERR("Failed to initialize common subsystem"); - return; - } + if (!common_initialized && ocre_common_init() != 0) { + LOG_ERR("Failed to initialize common subsystem"); + return; + } - ocre_register_cleanup_handler(OCRE_RESOURCE_TYPE_TIMER, ocre_timer_cleanup_container); - timer_system_initialized = true; - LOG_INF("Timer system initialized"); + ocre_register_cleanup_handler(OCRE_RESOURCE_TYPE_TIMER, ocre_timer_cleanup_container); + timer_system_initialized = true; + LOG_INF("Timer system initialized"); } -int ocre_timer_create(wasm_exec_env_t exec_env, int id) -{ - wasm_module_inst_t module = wasm_runtime_get_module_inst(exec_env); - if (!module || id <= 0 || id > CONFIG_MAX_TIMERS) { - LOG_ERR("Invalid module %p or timer ID %d (max: %d)", (void *)module, id, CONFIG_MAX_TIMERS); - return -EINVAL; - } - - ocre_timer_internal *timer = &timers[id - 1]; - if (timer->in_use) { - LOG_ERR("Timer ID %d already in use", id); - return -EBUSY; - } - - timer->id = id; - timer->owner = module; - timer->in_use = 1; - - // Initialize unified core timer - if (core_timer_init(&timer->timer, unified_timer_callback, timer) != 0) { - LOG_ERR("Failed to initialize core timer %d", id); - timer->in_use = 0; - return -EINVAL; - } - - ocre_increment_resource_count(module, OCRE_RESOURCE_TYPE_TIMER); - LOG_INF("Created timer %d for module %p", id, (void *)module); - return 0; +int ocre_timer_create(wasm_exec_env_t exec_env, int id) { + wasm_module_inst_t module = wasm_runtime_get_module_inst(exec_env); + if (!module || id <= 0 || id > CONFIG_MAX_TIMERS) { + LOG_ERR("Invalid module %p or timer ID %d (max: %d)", (void *)module, id, CONFIG_MAX_TIMERS); + return -EINVAL; + } + + ocre_timer_internal *timer = &timers[id - 1]; + if (timer->in_use) { + LOG_ERR("Timer ID %d already in use", id); + return -EBUSY; + } + + timer->id = id; + timer->owner = module; + timer->in_use = 1; + + // Initialize unified core timer + if (core_timer_init(&timer->timer, unified_timer_callback, timer) != 0) { + LOG_ERR("Failed to initialize core timer %d", id); + timer->in_use = 0; + return -EINVAL; + } + + ocre_increment_resource_count(module, OCRE_RESOURCE_TYPE_TIMER); + LOG_INF("Created timer %d for module %p", id, (void *)module); + return 0; } -int ocre_timer_delete(wasm_exec_env_t exec_env, ocre_timer_t id) -{ - wasm_module_inst_t module = wasm_runtime_get_module_inst(exec_env); - if (!module || id <= 0 || id > CONFIG_MAX_TIMERS) { - LOG_ERR("Invalid module %p or timer ID %d", (void *)module, id); - return -EINVAL; - } - - ocre_timer_internal *timer = &timers[id - 1]; - if (!timer->in_use || timer->owner != module) { - LOG_ERR("Timer ID %d not in use or not owned by module %p", id, (void *)module); - return -EINVAL; - } - - // Stop unified core timer - core_timer_stop(&timer->timer); - - timer->in_use = 0; - timer->running = 0; - timer->owner = NULL; - ocre_decrement_resource_count(module, OCRE_RESOURCE_TYPE_TIMER); - LOG_INF("Deleted timer %d", id); - return 0; +int ocre_timer_delete(wasm_exec_env_t exec_env, ocre_timer_t id) { + wasm_module_inst_t module = wasm_runtime_get_module_inst(exec_env); + if (!module || id <= 0 || id > CONFIG_MAX_TIMERS) { + LOG_ERR("Invalid module %p or timer ID %d", (void *)module, id); + return -EINVAL; + } + + ocre_timer_internal *timer = &timers[id - 1]; + if (!timer->in_use || timer->owner != module) { + LOG_ERR("Timer ID %d not in use or not owned by module %p", id, (void *)module); + return -EINVAL; + } + + // Stop unified core timer + core_timer_stop(&timer->timer); + + timer->in_use = 0; + timer->running = 0; + timer->owner = NULL; + ocre_decrement_resource_count(module, OCRE_RESOURCE_TYPE_TIMER); + LOG_INF("Deleted timer %d", id); + return 0; } -int ocre_timer_start(wasm_exec_env_t exec_env, ocre_timer_t id, int interval, int is_periodic) -{ - wasm_module_inst_t module = wasm_runtime_get_module_inst(exec_env); - if (!module || id <= 0 || id > CONFIG_MAX_TIMERS) { - LOG_ERR("Invalid module %p or timer ID %d", (void *)module, id); - return -EINVAL; - } - - ocre_timer_internal *timer = &timers[id - 1]; - if (!timer->in_use || timer->owner != module) { - LOG_ERR("Timer ID %d not in use or not owned by module %p", id, (void *)module); - return -EINVAL; - } - - if (interval <= 0 || interval > 65535) { - LOG_ERR("Invalid interval %dms (must be 1-65535ms)", interval); - return -EINVAL; - } - - timer->interval = interval; - timer->periodic = is_periodic; - timer->start_time = core_uptime_get(); - timer->running = 1; - - // Start unified core timer - int period_ms = is_periodic ? interval : 0; - if (core_timer_start(&timer->timer, interval, period_ms) != 0) { - LOG_ERR("Failed to start core timer %d", id); - timer->running = 0; - return -EINVAL; - } - - LOG_INF("Started timer %d with interval %dms, periodic=%d", id, interval, is_periodic); - return 0; +int ocre_timer_start(wasm_exec_env_t exec_env, ocre_timer_t id, int interval, int is_periodic) { + wasm_module_inst_t module = wasm_runtime_get_module_inst(exec_env); + if (!module || id <= 0 || id > CONFIG_MAX_TIMERS) { + LOG_ERR("Invalid module %p or timer ID %d", (void *)module, id); + return -EINVAL; + } + + ocre_timer_internal *timer = &timers[id - 1]; + if (!timer->in_use || timer->owner != module) { + LOG_ERR("Timer ID %d not in use or not owned by module %p", id, (void *)module); + return -EINVAL; + } + + if (interval <= 0 || interval > 65535) { + LOG_ERR("Invalid interval %dms (must be 1-65535ms)", interval); + return -EINVAL; + } + + timer->interval = interval; + timer->periodic = is_periodic; + timer->start_time = core_uptime_get(); + timer->running = 1; + + // Start unified core timer + int period_ms = is_periodic ? interval : 0; + if (core_timer_start(&timer->timer, interval, period_ms) != 0) { + LOG_ERR("Failed to start core timer %d", id); + timer->running = 0; + return -EINVAL; + } + + LOG_INF("Started timer %d with interval %dms, periodic=%d", id, interval, is_periodic); + return 0; } -int ocre_timer_stop(wasm_exec_env_t exec_env, ocre_timer_t id) -{ - wasm_module_inst_t module = wasm_runtime_get_module_inst(exec_env); - if (!module || id <= 0 || id > CONFIG_MAX_TIMERS) { - LOG_ERR("Invalid module %p or timer ID %d", (void *)module, id); - return -EINVAL; - } - - ocre_timer_internal *timer = &timers[id - 1]; - if (!timer->in_use || timer->owner != module) { - LOG_ERR("Timer ID %d not in use or not owned by module %p", id, (void *)module); - return -EINVAL; - } - - // Stop unified core timer - core_timer_stop(&timer->timer); - timer->running = 0; - - LOG_INF("Stopped timer %d", id); - return 0; +int ocre_timer_stop(wasm_exec_env_t exec_env, ocre_timer_t id) { + wasm_module_inst_t module = wasm_runtime_get_module_inst(exec_env); + if (!module || id <= 0 || id > CONFIG_MAX_TIMERS) { + LOG_ERR("Invalid module %p or timer ID %d", (void *)module, id); + return -EINVAL; + } + + ocre_timer_internal *timer = &timers[id - 1]; + if (!timer->in_use || timer->owner != module) { + LOG_ERR("Timer ID %d not in use or not owned by module %p", id, (void *)module); + return -EINVAL; + } + + // Stop unified core timer + core_timer_stop(&timer->timer); + timer->running = 0; + + LOG_INF("Stopped timer %d", id); + return 0; } -int ocre_timer_get_remaining(wasm_exec_env_t exec_env, ocre_timer_t id) -{ - wasm_module_inst_t module = wasm_runtime_get_module_inst(exec_env); - if (!module || id <= 0 || id > CONFIG_MAX_TIMERS) { - LOG_ERR("Invalid module %p or timer ID %d", (void *)module, id); - return -EINVAL; - } - - ocre_timer_internal *timer = &timers[id - 1]; - if (!timer->in_use || timer->owner != module) { - LOG_ERR("Timer ID %d not in use or not owned by module %p", id, (void *)module); - return -EINVAL; - } - - int remaining; - if (!timer->running) { - remaining = 0; - } else { - uint32_t current_time = core_uptime_get(); - uint32_t elapsed = current_time - timer->start_time; - if (elapsed >= timer->interval) { - remaining = 0; // Timer should have expired - } else { - remaining = timer->interval - elapsed; - } - } - - LOG_INF("Timer %d remaining time: %dms", id, remaining); - return remaining; +int ocre_timer_get_remaining(wasm_exec_env_t exec_env, ocre_timer_t id) { + wasm_module_inst_t module = wasm_runtime_get_module_inst(exec_env); + if (!module || id <= 0 || id > CONFIG_MAX_TIMERS) { + LOG_ERR("Invalid module %p or timer ID %d", (void *)module, id); + return -EINVAL; + } + + ocre_timer_internal *timer = &timers[id - 1]; + if (!timer->in_use || timer->owner != module) { + LOG_ERR("Timer ID %d not in use or not owned by module %p", id, (void *)module); + return -EINVAL; + } + + int remaining; + if (!timer->running) { + remaining = 0; + } else { + uint32_t current_time = core_uptime_get(); + uint32_t elapsed = current_time - timer->start_time; + if (elapsed >= timer->interval) { + remaining = 0; // Timer should have expired + } else { + remaining = timer->interval - elapsed; + } + } + + LOG_INF("Timer %d remaining time: %dms", id, remaining); + return remaining; } -void ocre_timer_cleanup_container(wasm_module_inst_t module_inst) -{ - if (!module_inst) { - LOG_ERR("Invalid module instance for cleanup"); - return; - } - - for (int i = 0; i < CONFIG_MAX_TIMERS; i++) { - if (timers[i].in_use && timers[i].owner == module_inst) { - // Stop unified core timer - core_timer_stop(&timers[i].timer); - timers[i].in_use = 0; - timers[i].running = 0; - timers[i].owner = NULL; - ocre_decrement_resource_count(module_inst, OCRE_RESOURCE_TYPE_TIMER); - LOG_DBG("Cleaned up timer %d for module %p", i + 1, (void *)module_inst); - } - } - LOG_DBG("Cleaned up timer resources for module %p", (void *)module_inst); +void ocre_timer_cleanup_container(wasm_module_inst_t module_inst) { + if (!module_inst) { + LOG_ERR("Invalid module instance for cleanup"); + return; + } + + for (int i = 0; i < CONFIG_MAX_TIMERS; i++) { + if (timers[i].in_use && timers[i].owner == module_inst) { + // Stop unified core timer + core_timer_stop(&timers[i].timer); + timers[i].in_use = 0; + timers[i].running = 0; + timers[i].owner = NULL; + ocre_decrement_resource_count(module_inst, OCRE_RESOURCE_TYPE_TIMER); + LOG_DBG("Cleaned up timer %d for module %p", i + 1, (void *)module_inst); + } + } + LOG_DBG("Cleaned up timer resources for module %p", (void *)module_inst); } /* Unified timer callback using core_timer API */ -static void unified_timer_callback(void *user_data) -{ - if (!timer_system_initialized || !common_initialized || !ocre_event_queue_initialized) { - LOG_ERR("Timer, common, or event queue not initialized, skipping callback"); - return; - } - - ocre_timer_internal *timer = (ocre_timer_internal *)user_data; - if (!timer || !timer->in_use || !timer->owner) { - LOG_ERR("Invalid timer in callback: %p", (void *)timer); - return; - } - - LOG_DBG("Timer callback for timer %d", timer->id); - - // For non-periodic timers, mark as not running - if (!timer->periodic) { - timer->running = 0; - } else { - // For periodic timers, update start time for next cycle - timer->start_time = core_uptime_get(); - } - - // Create and queue timer event - ocre_event_t event; - event.type = OCRE_RESOURCE_TYPE_TIMER; - event.data.timer_event.timer_id = timer->id; - event.owner = timer->owner; - - LOG_DBG("Creating timer event: type=%d, id=%d, for owner %p", event.type, timer->id, (void *)timer->owner); - - core_spinlock_key_t key = core_spinlock_lock(&ocre_event_queue_lock); - if (core_eventq_put(&ocre_event_queue, &event) != 0) { - LOG_ERR("Failed to queue timer event for timer %d", timer->id); - } else { - LOG_DBG("Queued timer event for timer %d", timer->id); - } - core_spinlock_unlock(&ocre_event_queue_lock, key); +static void unified_timer_callback(void *user_data) { + if (!timer_system_initialized || !common_initialized || !ocre_event_queue_initialized) { + LOG_ERR("Timer, common, or event queue not initialized, skipping callback"); + return; + } + + ocre_timer_internal *timer = (ocre_timer_internal *)user_data; + if (!timer || !timer->in_use || !timer->owner) { + LOG_ERR("Invalid timer in callback: %p", (void *)timer); + return; + } + + LOG_DBG("Timer callback for timer %d", timer->id); + + // For non-periodic timers, mark as not running + if (!timer->periodic) { + timer->running = 0; + } else { + // For periodic timers, update start time for next cycle + timer->start_time = core_uptime_get(); + } + + // Create and queue timer event + ocre_event_t event; + event.type = OCRE_RESOURCE_TYPE_TIMER; + event.data.timer_event.timer_id = timer->id; + event.owner = timer->owner; + + LOG_DBG("Creating timer event: type=%d, id=%d, for owner %p", event.type, timer->id, (void *)timer->owner); + + core_spinlock_key_t key = core_spinlock_lock(&ocre_event_queue_lock); + if (core_eventq_put(&ocre_event_queue, &event) != 0) { + LOG_ERR("Failed to queue timer event for timer %d", timer->id); + } else { + LOG_DBG("Queued timer event for timer %d", timer->id); + } + core_spinlock_unlock(&ocre_event_queue_lock, key); } diff --git a/src/ocre/shell/ocre_shell.c b/src/ocre/shell/ocre_shell.c index a60e0c0a..801b2193 100644 --- a/src/ocre/shell/ocre_shell.c +++ b/src/ocre/shell/ocre_shell.c @@ -1,157 +1,152 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -#include "ocre_shell.h" - -static ocre_cs_ctx *ctx_internal; - -int cmd_ocre_run(const struct shell *shell, size_t argc, char **argv) -{ - if (!ctx_internal) { - shell_error(shell, "Internal context not initialized."); - return -1; - } - - if (argc != 2) { - shell_error(shell, "Usage: ocre run "); - return -EINVAL; - } - - char *endptr; - int container_id = (int)strtol(argv[1], &endptr, 10); - - if (endptr == argv[1]) { - shell_error(shell, "No digits were found in argument .\n"); - return -EINVAL; - } else if (*endptr != '\0') { - shell_error(shell, "Invalid character: %c\n", *endptr); - return -EINVAL; - } - - int ret = -1; - for (int i = 0; i < CONFIG_MAX_CONTAINERS; i++) { - if (container_id == ctx_internal->containers[i].container_ID) { - ret = ocre_container_runtime_run_container(container_id, NULL); - break; - } - } - - if (ret == CONTAINER_STATUS_RUNNING) { - shell_info(shell, "Container started. Name: %s, ID: %d", - ctx_internal->containers[container_id].ocre_container_data.name, container_id); - return 0; - } else { - shell_error(shell, "Failed to run container: %d", container_id); - return -EIO; - } -} - -int cmd_ocre_stop(const struct shell *shell, size_t argc, char **argv) -{ - if (!ctx_internal) { - shell_error(shell, "Internal context not initialized."); - return -1; - } - - if (argc != 2) { - shell_error(shell, "Usage: ocre stop "); - return -EINVAL; - } - - const char *name = argv[1]; - shell_info(shell, "OCRE Shell Request to stop container with name: %s", name); - - int ret = -1; - int container_id = -1; - for (int i = 0; i < CONFIG_MAX_CONTAINERS; i++) { - if (strcmp(ctx_internal->containers[i].ocre_container_data.name, name) == 0) { - container_id = ctx_internal->containers[i].container_ID; - ret = ocre_container_runtime_stop_container(container_id, NULL); - } - } - - if (ret == CONTAINER_STATUS_STOPPED) { - shell_info(shell, "Container stopped. Name: %s, ID: %d", name, container_id); - } else if (ret == -1) { - shell_error(shell, "Failed to found container: %s", name); - } else { - shell_error(shell, "Failed to stop container: %s", name); - } - - return ret; -} - -int cmd_ocre_restart(const struct shell *shell, size_t argc, char **argv) -{ - if (!ctx_internal) { - shell_error(shell, "Internal context not initialized."); - return -1; - } - - if (argc != 2) { - shell_error(shell, "Usage: ocre restart "); - return -EINVAL; - } - - const char *name = argv[1]; - shell_info(shell, "OCRE Shell Request to restart container with name: %s", name); - - int ret = -1; - int container_id = -1; - for (int i = 0; i < CONFIG_MAX_CONTAINERS; i++) { - if (strcmp(ctx_internal->containers[i].ocre_container_data.name, name) == 0) { - container_id = ctx_internal->containers[i].container_ID; - ret = ocre_container_runtime_restart_container(ctx_internal, container_id, NULL); - } - } - - if (ret == CONTAINER_STATUS_RUNNING) { - shell_info(shell, "Container restarted. Name: %s, ID: %d", name, container_id); - } else if (ret == -1) { - shell_error(shell, "Failed to found container: %s", name); - } else { - shell_error(shell, "Failed to restart container: %s, status: %d", name, ret); - } - - return ret; -} - -int cmd_ocre_ls(const struct shell *shell, size_t argc, char **argv) -{ - ARG_UNUSED(argc); - ARG_UNUSED(argv); - - if (!ctx_internal) { - shell_error(shell, "Internal context not initialized."); - return -1; - } - - for (int i = 0; i < CONFIG_MAX_CONTAINERS; i++) { - shell_info(shell, "Container ID: %d, name: %s, status: %d", ctx_internal->containers[i].container_ID, - ctx_internal->containers[i].ocre_container_data.name, - ctx_internal->containers[i].container_runtime_status); - } - - return 0; -} - -void register_ocre_shell(ocre_cs_ctx *ctx) -{ - ctx_internal = ctx; - - SHELL_STATIC_SUBCMD_SET_CREATE( - ocre_subcmds, SHELL_CMD(run, NULL, "Start a new container: ocre run ", cmd_ocre_run), - SHELL_CMD(stop, NULL, "Stop a container: ocre stop ", cmd_ocre_stop), - SHELL_CMD(restart, NULL, "Restart a container: ocre restart ", cmd_ocre_restart), - SHELL_CMD(ls, NULL, "List running containers and their status", cmd_ocre_ls), SHELL_SUBCMD_SET_END); - -#if defined(CONFIG_OCRE_SHELL) - SHELL_CMD_REGISTER(ocre, &ocre_subcmds, "OCRE agent commands", NULL); -#endif -} +/** + * @copyright Copyright © contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "ocre_shell.h" + +static ocre_cs_ctx *ctx_internal; + +int cmd_ocre_run(const struct shell *shell, size_t argc, char **argv) { + if (!ctx_internal) { + shell_error(shell, "Internal context not initialized."); + return -1; + } + + if (argc != 2) { + shell_error(shell, "Usage: ocre run "); + return -EINVAL; + } + + char *endptr; + int container_id = (int)strtol(argv[1], &endptr, 10); + + if (endptr == argv[1]) { + shell_error(shell, "No digits were found in argument .\n"); + return -EINVAL; + } else if (*endptr != '\0') { + shell_error(shell, "Invalid character: %c\n", *endptr); + return -EINVAL; + } + + int ret = -1; + for (int i = 0; i < CONFIG_MAX_CONTAINERS; i++) { + if (container_id == ctx_internal->containers[i].container_ID) { + ret = ocre_container_runtime_run_container(container_id, NULL); + break; + } + } + + if (ret == CONTAINER_STATUS_RUNNING) { + shell_info(shell, "Container started. Name: %s, ID: %d", + ctx_internal->containers[container_id].ocre_container_data.name, container_id); + return 0; + } else { + shell_error(shell, "Failed to run container: %d", container_id); + return -EIO; + } +} + +int cmd_ocre_stop(const struct shell *shell, size_t argc, char **argv) { + if (!ctx_internal) { + shell_error(shell, "Internal context not initialized."); + return -1; + } + + if (argc != 2) { + shell_error(shell, "Usage: ocre stop "); + return -EINVAL; + } + + const char *name = argv[1]; + shell_info(shell, "OCRE Shell Request to stop container with name: %s", name); + + int ret = -1; + int container_id = -1; + for (int i = 0; i < CONFIG_MAX_CONTAINERS; i++) { + if (strcmp(ctx_internal->containers[i].ocre_container_data.name, name) == 0) { + container_id = ctx_internal->containers[i].container_ID; + ret = ocre_container_runtime_stop_container(container_id, NULL); + } + } + + if (ret == CONTAINER_STATUS_STOPPED) { + shell_info(shell, "Container stopped. Name: %s, ID: %d", name, container_id); + } else if (ret == -1) { + shell_error(shell, "Failed to found container: %s", name); + } else { + shell_error(shell, "Failed to stop container: %s", name); + } + + return ret; +} + +int cmd_ocre_restart(const struct shell *shell, size_t argc, char **argv) { + if (!ctx_internal) { + shell_error(shell, "Internal context not initialized."); + return -1; + } + + if (argc != 2) { + shell_error(shell, "Usage: ocre restart "); + return -EINVAL; + } + + const char *name = argv[1]; + shell_info(shell, "OCRE Shell Request to restart container with name: %s", name); + + int ret = -1; + int container_id = -1; + for (int i = 0; i < CONFIG_MAX_CONTAINERS; i++) { + if (strcmp(ctx_internal->containers[i].ocre_container_data.name, name) == 0) { + container_id = ctx_internal->containers[i].container_ID; + ret = ocre_container_runtime_restart_container(ctx_internal, container_id, NULL); + } + } + + if (ret == CONTAINER_STATUS_RUNNING) { + shell_info(shell, "Container restarted. Name: %s, ID: %d", name, container_id); + } else if (ret == -1) { + shell_error(shell, "Failed to found container: %s", name); + } else { + shell_error(shell, "Failed to restart container: %s, status: %d", name, ret); + } + + return ret; +} + +int cmd_ocre_ls(const struct shell *shell, size_t argc, char **argv) { + ARG_UNUSED(argc); + ARG_UNUSED(argv); + + if (!ctx_internal) { + shell_error(shell, "Internal context not initialized."); + return -1; + } + + for (int i = 0; i < CONFIG_MAX_CONTAINERS; i++) { + shell_info(shell, "Container ID: %d, name: %s, status: %d", ctx_internal->containers[i].container_ID, + ctx_internal->containers[i].ocre_container_data.name, + ctx_internal->containers[i].container_runtime_status); + } + + return 0; +} + +void register_ocre_shell(ocre_cs_ctx *ctx) { + ctx_internal = ctx; + + SHELL_STATIC_SUBCMD_SET_CREATE( + ocre_subcmds, SHELL_CMD(run, NULL, "Start a new container: ocre run ", cmd_ocre_run), + SHELL_CMD(stop, NULL, "Stop a container: ocre stop ", cmd_ocre_stop), + SHELL_CMD(restart, NULL, "Restart a container: ocre restart ", cmd_ocre_restart), + SHELL_CMD(ls, NULL, "List running containers and their status", cmd_ocre_ls), SHELL_SUBCMD_SET_END); + +#if defined(CONFIG_OCRE_SHELL) + SHELL_CMD_REGISTER(ocre, &ocre_subcmds, "OCRE agent commands", NULL); +#endif +} diff --git a/src/ocre/shell/ocre_shell.h b/src/ocre/shell/ocre_shell.h index 56238c85..3bb0bb81 100644 --- a/src/ocre/shell/ocre_shell.h +++ b/src/ocre/shell/ocre_shell.h @@ -1,22 +1,22 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef OCRE_SHELL_H -#define OCRE_SHELL_H - -#include -#include "../src/ocre/ocre_container_runtime/ocre_container_runtime.h" - -// Function declarations for `config` subcommand handlers -int cmd_ocre_run(const struct shell *shell, size_t argc, char **argv); -int cmd_ocre_stop(const struct shell *shell, size_t argc, char **argv); -int cmd_ocre_ps(const struct shell *shell, size_t argc, char **argv); - -// Command registration function -void register_ocre_shell(ocre_cs_ctx *ctx); - -#endif /* OCRE_SHELL_H */ +/** + * @copyright Copyright © contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef OCRE_SHELL_H +#define OCRE_SHELL_H + +#include +#include "../src/ocre/ocre_container_runtime/ocre_container_runtime.h" + +// Function declarations for `config` subcommand handlers +int cmd_ocre_run(const struct shell *shell, size_t argc, char **argv); +int cmd_ocre_stop(const struct shell *shell, size_t argc, char **argv); +int cmd_ocre_ps(const struct shell *shell, size_t argc, char **argv); + +// Command registration function +void register_ocre_shell(ocre_cs_ctx *ctx); + +#endif /* OCRE_SHELL_H */ diff --git a/src/ocre/sm/sm.c b/src/ocre/sm/sm.c index cd72e30f..4c0068a2 100644 --- a/src/ocre/sm/sm.c +++ b/src/ocre/sm/sm.c @@ -16,85 +16,79 @@ #include "sm.h" LOG_MODULE_REGISTER(state_machine, OCRE_LOG_LEVEL); -void sm_init(state_machine_t *sm, core_mq_t *msgq, void *msg, void *custom_ctx, const struct smf_state *hsm) -{ - sm->hsm = hsm; - sm->msgq = msgq; - sm->ctx.event.msg = msg; - sm->ctx.custom_ctx = custom_ctx; +void sm_init(state_machine_t *sm, core_mq_t *msgq, void *msg, void *custom_ctx, const struct smf_state *hsm) { + sm->hsm = hsm; + sm->msgq = msgq; + sm->ctx.event.msg = msg; + sm->ctx.custom_ctx = custom_ctx; } -int sm_run(state_machine_t *sm, int initial_state) -{ - int ret; +int sm_run(state_machine_t *sm, int initial_state) { + int ret; - smf_set_initial(SMF_CTX(&sm->ctx), &sm->hsm[initial_state]); + smf_set_initial(SMF_CTX(&sm->ctx), &sm->hsm[initial_state]); - while (true) { - // Wait for a message from the queue - core_mq_recv(sm->msgq, sm->ctx.event.msg); - sm->ctx.event.handled = false; + while (true) { + // Wait for a message from the queue + core_mq_recv(sm->msgq, sm->ctx.event.msg); + sm->ctx.event.handled = false; - ret = smf_run_state(SMF_CTX(&sm->ctx)); + ret = smf_run_state(SMF_CTX(&sm->ctx)); - if (ret) { - LOG_ERR("State machine error: %d", ret); - break; - } + if (ret) { + LOG_ERR("State machine error: %d", ret); + break; + } - if (!sm->ctx.event.handled) { - struct ocre_message const *msg = SM_GET_EVENT(&sm->ctx); - LOG_ERR("Unhandled event: msg type or data = %d", msg->event); - } + if (!sm->ctx.event.handled) { + struct ocre_message const *msg = SM_GET_EVENT(&sm->ctx); + LOG_ERR("Unhandled event: msg type or data = %d", msg->event); + } - // Yield the current thread to allow the queue events to be processed - core_yield(); - } + // Yield the current thread to allow the queue events to be processed + core_yield(); + } - return ret; + return ret; } -int sm_transition(state_machine_t *sm, int target_state) -{ - if (!sm->hsm) { - LOG_ERR("State machine has not been initialized"); - return -EINVAL; - } +int sm_transition(state_machine_t *sm, int target_state) { + if (!sm->hsm) { + LOG_ERR("State machine has not been initialized"); + return -EINVAL; + } - smf_set_state(SMF_CTX(&sm->ctx), &sm->hsm[target_state]); + smf_set_state(SMF_CTX(&sm->ctx), &sm->hsm[target_state]); - return 0; + return 0; } -int sm_init_event_timer(state_machine_t *sm, int timer_id, void *timer_cb) -{ - if (timer_id < 0 || timer_id >= MAX_TIMERS) { - LOG_ERR("Invalid timer id: %d", timer_id); - return -EINVAL; - } - - core_timer_init(&sm->timers[timer_id], timer_cb, NULL); - return 0; +int sm_init_event_timer(state_machine_t *sm, int timer_id, void *timer_cb) { + if (timer_id < 0 || timer_id >= MAX_TIMERS) { + LOG_ERR("Invalid timer id: %d", timer_id); + return -EINVAL; + } + + core_timer_init(&sm->timers[timer_id], timer_cb, NULL); + return 0; } -int sm_set_event_timer(state_machine_t *sm, int timer_id, int duration, int period) -{ - if (timer_id < 0 || timer_id >= MAX_TIMERS) { - LOG_ERR("Invalid timer id: %d", timer_id); - return -EINVAL; - } +int sm_set_event_timer(state_machine_t *sm, int timer_id, int duration, int period) { + if (timer_id < 0 || timer_id >= MAX_TIMERS) { + LOG_ERR("Invalid timer id: %d", timer_id); + return -EINVAL; + } - core_timer_start(&sm->timers[timer_id], duration, period); - return 0; + core_timer_start(&sm->timers[timer_id], duration, period); + return 0; } -int sm_clear_event_timer(state_machine_t *sm, int timer_id) -{ - if (timer_id < 0 || timer_id >= MAX_TIMERS) { - LOG_ERR("Invalid timer id: %d", timer_id); - return -EINVAL; - } +int sm_clear_event_timer(state_machine_t *sm, int timer_id) { + if (timer_id < 0 || timer_id >= MAX_TIMERS) { + LOG_ERR("Invalid timer id: %d", timer_id); + return -EINVAL; + } - core_timer_stop(&sm->timers[timer_id]); - return 0; + core_timer_stop(&sm->timers[timer_id]); + return 0; } diff --git a/src/ocre/sm/sm.h b/src/ocre/sm/sm.h index ec0fbb6b..f2fd9803 100644 --- a/src/ocre/sm/sm.h +++ b/src/ocre/sm/sm.h @@ -13,28 +13,28 @@ #define MAX_TIMERS 3 #define SM_RETURN_IF_EVENT_HANDLED(o) \ - if (((struct sm_ctx *)o)->event.handled) \ - return SMF_EVENT_HANDLED + if (((struct sm_ctx *)o)->event.handled) \ + return SMF_EVENT_HANDLED #define SM_MARK_EVENT_HANDLED(o) ((struct sm_ctx *)o)->event.handled = true -#define SM_GET_EVENT(o) ((struct sm_ctx *)o)->event.msg -#define SM_GET_CUSTOM_CTX(o) ((struct sm_ctx *)o)->custom_ctx +#define SM_GET_EVENT(o) ((struct sm_ctx *)o)->event.msg +#define SM_GET_CUSTOM_CTX(o) ((struct sm_ctx *)o)->custom_ctx #define EVENT_LOG_MSG(fmt, event) LOG_DBG(fmt, event) struct sm_ctx { - struct smf_ctx ctx; - struct { - bool handled; - void *msg; - } event; - void *custom_ctx; + struct smf_ctx ctx; + struct { + bool handled; + void *msg; + } event; + void *custom_ctx; }; typedef struct state_machine { - core_mq_t *msgq; - core_timer_t timers[MAX_TIMERS]; - struct sm_ctx ctx; /*!< State machine context */ - const struct smf_state *hsm; /*!< State machine states */ + core_mq_t *msgq; + core_timer_t timers[MAX_TIMERS]; + struct sm_ctx ctx; /*!< State machine context */ + const struct smf_state *hsm; /*!< State machine states */ } state_machine_t; int sm_transition(state_machine_t *sm, int target_state); diff --git a/src/ocre/utils/c-smf/smf/smf.c b/src/ocre/utils/c-smf/smf/smf.c index 74bc1ba6..dde5bbce 100644 --- a/src/ocre/utils/c-smf/smf/smf.c +++ b/src/ocre/utils/c-smf/smf/smf.c @@ -16,10 +16,10 @@ * member of the smf_ctx structure. */ struct internal_ctx { - bool new_state : 1; - bool terminate : 1; - bool is_exit : 1; - bool handled : 1; + bool new_state: 1; + bool terminate: 1; + bool is_exit: 1; + bool handled: 1; }; #ifdef CONFIG_SMF_ANCESTOR_SUPPORT @@ -34,7 +34,8 @@ static bool share_parent(const struct smf_state *test_state, const struct smf_st return false; } -static const struct smf_state *get_child_of(const struct smf_state *states, const struct smf_state *parent) +static const struct smf_state *get_child_of(const struct smf_state *states, + const struct smf_state *parent) { const struct smf_state *tmp = states; @@ -63,9 +64,11 @@ static const struct smf_state *get_last_of(const struct smf_state *states) * @param dest transition destination * @return LCA state, or NULL if states have no LCA. */ -static const struct smf_state *get_lca_of(const struct smf_state *source, const struct smf_state *dest) +static const struct smf_state *get_lca_of(const struct smf_state *source, + const struct smf_state *dest) { - for (const struct smf_state *ancestor = source->parent; ancestor != NULL; ancestor = ancestor->parent) { + for (const struct smf_state *ancestor = source->parent; ancestor != NULL; + ancestor = ancestor->parent) { if (ancestor == dest) { return ancestor->parent; } else if (share_parent(dest, ancestor)) { @@ -84,7 +87,8 @@ static const struct smf_state *get_lca_of(const struct smf_state *source, const * @param topmost State we are entering from. Its entry action is not executed * @return true if the state machine should terminate, else false */ -static bool smf_execute_all_entry_actions(struct smf_ctx *const ctx, const struct smf_state *new_state, +static bool smf_execute_all_entry_actions(struct smf_ctx *const ctx, + const struct smf_state *new_state, const struct smf_state *topmost) { struct internal_ctx *const internal = (void *)&ctx->internal; @@ -95,7 +99,8 @@ static bool smf_execute_all_entry_actions(struct smf_ctx *const ctx, const struc } for (const struct smf_state *to_execute = get_child_of(new_state, topmost); - to_execute != NULL && to_execute != new_state; to_execute = get_child_of(new_state, to_execute)) { + to_execute != NULL && to_execute != new_state; + to_execute = get_child_of(new_state, to_execute)) { /* Keep track of the executing entry action in case it calls * smf_set_state() */ @@ -187,8 +192,8 @@ static bool smf_execute_all_exit_actions(struct smf_ctx *const ctx, const struct { struct internal_ctx *const internal = (void *)&ctx->internal; - for (const struct smf_state *to_execute = ctx->current; to_execute != NULL && to_execute != topmost; - to_execute = to_execute->parent) { + for (const struct smf_state *to_execute = ctx->current; + to_execute != NULL && to_execute != topmost; to_execute = to_execute->parent) { if (to_execute->exit) { to_execute->exit(ctx); diff --git a/src/ocre/utils/c-smf/test/test.c b/src/ocre/utils/c-smf/test/test.c index 25440810..ebf7ea64 100644 --- a/src/ocre/utils/c-smf/test/test.c +++ b/src/ocre/utils/c-smf/test/test.c @@ -2,79 +2,72 @@ #include "../smf/smf.h" // Define state entry, exit, and run actions -void state1_entry(void *ctx) -{ - (void)ctx; /* -Wunused-parameter */ - printf("Entering State 1\n"); +void state1_entry(void *ctx) { + (void)ctx; /* -Wunused-parameter */ + printf("Entering State 1\n"); } -void state1_exit(void *ctx) -{ - (void)ctx; /* -Wunused-parameter */ - printf("Exiting State 1\n"); +void state1_exit(void *ctx) { + (void)ctx; /* -Wunused-parameter */ + printf("Exiting State 1\n"); } -void state1_run(void *ctx) -{ - (void)ctx; /* -Wunused-parameter */ - printf("Running State 1\n"); +void state1_run(void *ctx) { + (void)ctx; /* -Wunused-parameter */ + printf("Running State 1\n"); } -void state2_entry(void *ctx) -{ - (void)ctx; /* -Wunused-parameter */ - printf("Entering State 2\n"); +void state2_entry(void *ctx) { + (void)ctx; /* -Wunused-parameter */ + printf("Entering State 2\n"); } -void state2_exit(void *ctx) -{ - (void)ctx; /* -Wunused-parameter */ - printf("Exiting State 2\n"); +void state2_exit(void *ctx) { + (void)ctx; /* -Wunused-parameter */ + printf("Exiting State 2\n"); } -void state2_run(void *ctx) -{ - (void)ctx; /* -Wunused-parameter */ - printf("Running State 2\n"); +void state2_run(void *ctx) { + (void)ctx; /* -Wunused-parameter */ + printf("Running State 2\n"); } // Define states struct smf_state state1 = { - .entry = state1_entry, - .run = state1_run, - .exit = state1_exit, + .entry = state1_entry, + .run = state1_run, + .exit = state1_exit, #ifdef CONFIG_SMF_ANCESTOR_SUPPORT - .parent = NULL, + .parent = NULL, #endif /* CONFIG_SMF_ANCESTOR_SUPPORT */ }; struct smf_state state2 = { - .entry = state2_entry, - .run = state2_run, - .exit = state2_exit, + .entry = state2_entry, + .run = state2_run, + .exit = state2_exit, #ifdef CONFIG_SMF_ANCESTOR_SUPPORT - .parent = NULL, + .parent = NULL, #endif /* CONFIG_SMF_ANCESTOR_SUPPORT */ }; -int main() -{ - struct smf_ctx ctx; +int main() { + struct smf_ctx ctx; - // Initialize the state machine with the initial state - smf_set_initial(&ctx, &state1); + // Initialize the state machine with the initial state + smf_set_initial(&ctx, &state1); - // Run the initial state - printf("Starting State Machine\n"); - smf_run_state(&ctx); + // Run the initial state + printf("Starting State Machine\n"); + smf_run_state(&ctx); - // Transition to a new state - printf("Transitioning to State 2\n"); - smf_set_state(&ctx, &state2); + // Transition to a new state + printf("Transitioning to State 2\n"); + smf_set_state(&ctx, &state2); - // Run the new state - smf_run_state(&ctx); + // Run the new state + smf_run_state(&ctx); - printf("State Machine Test Complete\n"); - return 0; + printf("State Machine Test Complete\n"); + return 0; } \ No newline at end of file diff --git a/src/ocre/utils/strlcat.c b/src/ocre/utils/strlcat.c index 57c3c37b..f3597793 100644 --- a/src/ocre/utils/strlcat.c +++ b/src/ocre/utils/strlcat.c @@ -26,29 +26,32 @@ * Returns strlen(src) + MIN(dsize, strlen(initial dst)). * If retval >= dsize, truncation occurred. */ -size_t strlcat(char *dst, const char *src, size_t dsize) +size_t +strlcat (char *dst, + const char *src, + size_t dsize) { - const char *odst = dst; - const char *osrc = src; - size_t n = dsize; - size_t dlen; + const char *odst = dst; + const char *osrc = src; + size_t n = dsize; + size_t dlen; - /* Find the end of dst and adjust bytes left but don't go past end. */ - while (n-- != 0 && *dst != '\0') - dst++; - dlen = dst - odst; - n = dsize - dlen; + /* Find the end of dst and adjust bytes left but don't go past end. */ + while (n-- != 0 && *dst != '\0') + dst++; + dlen = dst - odst; + n = dsize - dlen; - if (n-- == 0) - return (dlen + strlen(src)); - while (*src != '\0') { - if (n != 0) { - *dst++ = *src; - n--; - } - src++; - } - *dst = '\0'; + if (n-- == 0) + return(dlen + strlen(src)); + while (*src != '\0') { + if (n != 0) { + *dst++ = *src; + n--; + } + src++; + } + *dst = '\0'; - return (dlen + (src - osrc)); /* count does not include NUL */ + return(dlen + (src - osrc)); /* count does not include NUL */ } diff --git a/src/samples-mini/posix/main.c b/src/samples-mini/posix/main.c index a28d7483..67c781d2 100644 --- a/src/samples-mini/posix/main.c +++ b/src/samples-mini/posix/main.c @@ -27,59 +27,57 @@ void create_sample_container(); -int main(int argc, char *argv[]) -{ - ocre_cs_ctx ctx; - ocre_container_init_arguments_t args; - char *container_filename = "hello"; - - ocre_app_storage_init(); - - // Step 1: Initialize the Ocre runtime - ocre_container_runtime_status_t ret = ocre_container_runtime_init(&ctx, &args); - - if (ret == RUNTIME_STATUS_INITIALIZED) { - printf("\n\nOcre runtime started\n"); - - if (argc > 1) { - set_argc(argc); - container_filename = argv[1]; // Use the filename as the container name/sha256 - } else { - create_sample_container(container_filename); - } - - // Step 2: Create the container, this allocates and loads the container binary - ocre_container_data_t ocre_container_data[CONFIG_MAX_CONTAINERS]; - int container_ID[CONFIG_MAX_CONTAINERS]; - ocre_container_runtime_cb callback[CONFIG_MAX_CONTAINERS]; - - int i = 0; - do { - ocre_container_data[i].heap_size = 0; - snprintf(ocre_container_data[i].name, sizeof(ocre_container_data[i].name), "Container%d", i); - snprintf(ocre_container_data[i].sha256, sizeof(ocre_container_data[i].sha256), "%s", - container_filename); - ocre_container_data[i].timers = 0; - ocre_container_data[i].watchdog_interval = 0; - ocre_container_runtime_create_container(&ctx, &ocre_container_data[i], &container_ID[i], - callback[i]); - - // Step 3: Execute the container - ocre_container_runtime_run_container(container_ID[i], callback[i]); - core_sleep_ms(1000); - - i++; - container_filename = argv[i + 1]; - } while (i < argc - 1); - - // Loop forever, without this the application will exit and stop all execution - while (true) { - core_sleep_ms(1000); - } - - } else { - printf("\n\nOcre runtime failed to start.\n"); - } +int main(int argc, char *argv[]) { + ocre_cs_ctx ctx; + ocre_container_init_arguments_t args; + char *container_filename = "hello"; + + ocre_app_storage_init(); + + // Step 1: Initialize the Ocre runtime + ocre_container_runtime_status_t ret = ocre_container_runtime_init(&ctx, &args); + + if (ret == RUNTIME_STATUS_INITIALIZED) { + printf("\n\nOcre runtime started\n"); + + if (argc > 1) { + set_argc(argc); + container_filename = argv[1]; // Use the filename as the container name/sha256 + } + else { + create_sample_container(container_filename); + } + + // Step 2: Create the container, this allocates and loads the container binary + ocre_container_data_t ocre_container_data[CONFIG_MAX_CONTAINERS]; + int container_ID[CONFIG_MAX_CONTAINERS]; + ocre_container_runtime_cb callback[CONFIG_MAX_CONTAINERS]; + + int i = 0; + do { + ocre_container_data[i].heap_size = 0; + snprintf(ocre_container_data[i].name, sizeof(ocre_container_data[i].name), "Container%d", i); + snprintf(ocre_container_data[i].sha256, sizeof(ocre_container_data[i].sha256), "%s", container_filename); + ocre_container_data[i].timers = 0; + ocre_container_data[i].watchdog_interval = 0; + ocre_container_runtime_create_container(&ctx, &ocre_container_data[i], &container_ID[i], callback[i]); + + // Step 3: Execute the container + ocre_container_runtime_run_container(container_ID[i], callback[i]); + core_sleep_ms(1000); + + i++; + container_filename = argv[i+1]; + } while (i < argc - 1); + + // Loop forever, without this the application will exit and stop all execution + while (true) { + core_sleep_ms(1000); + } + + } else { + printf("\n\nOcre runtime failed to start.\n"); + } } /** @@ -89,29 +87,28 @@ int main(int argc, char *argv[]) * @param file_name a string containing the name of the file to create */ -void create_sample_container(char *file_name) -{ - static char file_path[64]; - snprintf(file_path, sizeof(file_path), "./%s/%s.bin", APP_RESOURCE_PATH, file_name); - - // Create directories if they don't exist - mkdir("./ocre", 0755); - mkdir("./ocre/images", 0755); - - // Open the file for writing - int fd = open(file_path, O_CREAT | O_RDWR, 0644); - if (fd == -1) { - perror("Error opening file"); - return; - } - // Write the binary data to the file - ssize_t bytes_written = write(fd, wasm_binary, wasm_binary_len); - if (bytes_written == -1) { - perror("Error writing to file"); - } else { - printf("Wrote %zd bytes to %s\n", bytes_written, file_path); - } - - // Close the file - close(fd); +void create_sample_container(char *file_name) { + static char file_path[64]; + snprintf(file_path, sizeof(file_path), "./%s/%s.bin", APP_RESOURCE_PATH, file_name); + + // Create directories if they don't exist + mkdir("./ocre", 0755); + mkdir("./ocre/images", 0755); + + // Open the file for writing + int fd = open(file_path, O_CREAT | O_RDWR, 0644); + if (fd == -1) { + perror("Error opening file"); + return; + } + // Write the binary data to the file + ssize_t bytes_written = write(fd, wasm_binary, wasm_binary_len); + if (bytes_written == -1) { + perror("Error writing to file"); + } else { + printf("Wrote %zd bytes to %s\n", bytes_written, file_path); + } + + // Close the file + close(fd); } diff --git a/src/samples-mini/zephyr/main.c b/src/samples-mini/zephyr/main.c index 0927ae7a..034baed0 100644 --- a/src/samples-mini/zephyr/main.c +++ b/src/samples-mini/zephyr/main.c @@ -23,55 +23,54 @@ void create_sample_container(); int ocre_network_init(); -int main(int argc, char *argv[]) -{ - ocre_cs_ctx ctx; - ocre_container_init_arguments_t args; +int main(int argc, char *argv[]) { + ocre_cs_ctx ctx; + ocre_container_init_arguments_t args; #ifdef OCRE_INPUT_FILE_NAME - const char *container_filename = OCRE_INPUT_FILE_NAME; + const char *container_filename = OCRE_INPUT_FILE_NAME; #else - const char *container_filename = "hello-from-ocre"; + const char *container_filename = "hello-from-ocre"; #endif #ifdef CONFIG_OCRE_NETWORKING - int net_status = ocre_network_init(); - if (net_status < 0) { - printf("Unable to connect to network\n"); - } else { - printf("Network is UP\n"); - } + int net_status = ocre_network_init(); + if (net_status < 0) { + printf("Unable to connect to network\n"); + } else { + printf("Network is UP\n"); + } #endif - ocre_app_storage_init(); + ocre_app_storage_init(); - // Step 1: Initialize the Ocre runtime - ocre_container_runtime_status_t ret = ocre_container_runtime_init(&ctx, &args); + // Step 1: Initialize the Ocre runtime + ocre_container_runtime_status_t ret = ocre_container_runtime_init(&ctx, &args); - if (ret == RUNTIME_STATUS_INITIALIZED) { - printf("\n\nOcre runtime started\n"); + if (ret == RUNTIME_STATUS_INITIALIZED) { + printf("\n\nOcre runtime started\n"); - create_sample_container(container_filename); + create_sample_container(container_filename); - // Step 2: Create the container, this allocates and loads the container binary - ocre_container_data_t ocre_container_data; - int container_ID; + // Step 2: Create the container, this allocates and loads the container binary + ocre_container_data_t ocre_container_data; + int container_ID; - ocre_container_data.heap_size = 0; - snprintf(ocre_container_data.name, sizeof(ocre_container_data.name), "%s", container_filename); - snprintf(ocre_container_data.sha256, sizeof(ocre_container_data.sha256), "%s", container_filename); - ocre_container_data.timers = 0; - ocre_container_runtime_create_container(&ctx, &ocre_container_data, &container_ID, NULL); + ocre_container_data.heap_size = 0; + snprintf(ocre_container_data.name, sizeof(ocre_container_data.name), "%s", container_filename); + snprintf(ocre_container_data.sha256, sizeof(ocre_container_data.sha256), "%s", container_filename); + ocre_container_data.timers = 0; + ocre_container_runtime_create_container(&ctx, &ocre_container_data, &container_ID, NULL); - // Step 3: Execute the container - ocre_container_runtime_run_container(container_ID, NULL); - // Loop forever, without this the application will exit and stop all execution - while (true) { - core_sleep_ms(1000); - } + // Step 3: Execute the container + ocre_container_runtime_run_container(container_ID, NULL); + // Loop forever, without this the application will exit and stop all execution + while (true) { + core_sleep_ms(1000); + } - } else { - printf("\n\nOcre runtime failed to start.\n"); - } + } else { + printf("\n\nOcre runtime failed to start.\n"); + } } /** @@ -81,37 +80,35 @@ int main(int argc, char *argv[]) * @param file_name a string containing the name of the file to create */ -void create_sample_container(char *file_name) -{ - static char file_path[64]; - struct fs_file_t f; - snprintf((char *)&file_path, 64, "/lfs/ocre/images/%s.bin", file_name); - int res; +void create_sample_container(char *file_name) { + static char file_path[64]; + struct fs_file_t f; + snprintf((char *)&file_path, 64, "/lfs/ocre/images/%s.bin", file_name); + int res; - fs_file_t_init(&f); - res = fs_open(&f, file_path, FS_O_CREATE | FS_O_TRUNC | FS_O_RDWR); + fs_file_t_init(&f); + res = fs_open(&f, file_path, FS_O_CREATE | FS_O_TRUNC | FS_O_RDWR); - fs_write(&f, &wasm_binary, wasm_binary_len); - fs_close(&f); + fs_write(&f, &wasm_binary, wasm_binary_len); + fs_close(&f); } -int ocre_network_init() -{ +int ocre_network_init() { - struct net_if *iface = net_if_get_default(); - net_dhcpv4_start(iface); + struct net_if *iface = net_if_get_default(); + net_dhcpv4_start(iface); - printf("Waiting for network to be ready...\n"); + printf("Waiting for network to be ready...\n"); - int sleep_cnt = 0; - while (!net_if_is_up(iface) && (sleep_cnt < 10)) { - k_sleep(K_MSEC(200)); - sleep_cnt++; - } + int sleep_cnt = 0; + while (!net_if_is_up(iface) && (sleep_cnt < 10)) { + k_sleep(K_MSEC(200)); + sleep_cnt++; + } - if (!net_if_is_up(iface)) { - return -ENOTCONN; - } + if (!net_if_is_up(iface)) { + return -ENOTCONN; + } - return 0; + return 0; } diff --git a/src/shared/platform/ocre_core_external.h b/src/shared/platform/ocre_core_external.h index 1b852125..69375219 100644 --- a/src/shared/platform/ocre_core_external.h +++ b/src/shared/platform/ocre_core_external.h @@ -45,8 +45,7 @@ typedef struct core_thread core_thread_t; * @param priority Thread priority. * @return 0 on success, negative value on error. */ -int core_thread_create(core_thread_t *thread, core_thread_func_t func, void *arg, const char *name, size_t stack_size, - int priority); +int core_thread_create(core_thread_t *thread, core_thread_func_t func, void *arg, const char *name, size_t stack_size, int priority); /** * @brief Destroy a thread and release its resources. diff --git a/src/shared/platform/ocre_psram.h b/src/shared/platform/ocre_psram.h index 6f37e98d..1072b49b 100644 --- a/src/shared/platform/ocre_psram.h +++ b/src/shared/platform/ocre_psram.h @@ -3,29 +3,29 @@ // PSRAM configuration - centralized for different platforms #if defined(CONFIG_MEMC) -// Board-specific PSRAM section attributes -#if defined(CONFIG_BOARD_ARDUINO_PORTENTA_H7) -#define PSRAM_SECTION_ATTR __attribute__((section("SDRAM1"), aligned(32))) -#elif defined(CONFIG_BOARD_B_U585I_IOT02A) -#define PSRAM_SECTION_ATTR __attribute__((section(".stm32_psram"), aligned(32))) -#elif defined(CONFIG_BOARD_MIMXRT1064_EVK) -#define PSRAM_SECTION_ATTR __attribute__((section("SDRAM"), aligned(32))) -#else -#define PSRAM_SECTION_ATTR __attribute__((aligned(32))) -#endif - -PSRAM_SECTION_ATTR -static char storage_heap_buf[CONFIG_OCRE_STORAGE_HEAP_BUFFER_SIZE] = {0}; + // Board-specific PSRAM section attributes + #if defined(CONFIG_BOARD_ARDUINO_PORTENTA_H7) + #define PSRAM_SECTION_ATTR __attribute__((section("SDRAM1"), aligned(32))) + #elif defined(CONFIG_BOARD_B_U585I_IOT02A) + #define PSRAM_SECTION_ATTR __attribute__((section(".stm32_psram"), aligned(32))) + #elif defined(CONFIG_BOARD_MIMXRT1064_EVK) + #define PSRAM_SECTION_ATTR __attribute__((section("SDRAM"), aligned(32))) + #else + #define PSRAM_SECTION_ATTR __attribute__((aligned(32))) + #endif -static struct k_heap storage_heap; -#define storage_heap_init() k_heap_init(&storage_heap, storage_heap_buf, CONFIG_OCRE_STORAGE_HEAP_BUFFER_SIZE) -#define storage_heap_alloc(size) k_heap_alloc(&storage_heap, (size), K_SECONDS(1)) -#define storage_heap_free(buffer) k_heap_free(&storage_heap, (void *)buffer) + PSRAM_SECTION_ATTR + static char storage_heap_buf[CONFIG_OCRE_STORAGE_HEAP_BUFFER_SIZE] = {0}; + + static struct k_heap storage_heap; + #define storage_heap_init() k_heap_init(&storage_heap, storage_heap_buf, CONFIG_OCRE_STORAGE_HEAP_BUFFER_SIZE) + #define storage_heap_alloc(size) k_heap_alloc(&storage_heap, (size), K_SECONDS(1)) + #define storage_heap_free(buffer) k_heap_free(&storage_heap, (void*)buffer) #else -// No PSRAM - use system malloc -#define storage_heap_init() /* No initialization needed */ -#define storage_heap_alloc(size) malloc(size) -#define storage_heap_free(buffer) free(buffer) + // No PSRAM - use system malloc + #define storage_heap_init() /* No initialization needed */ + #define storage_heap_alloc(size) malloc(size) + #define storage_heap_free(buffer) free(buffer) #endif #endif /* OCRE_PSRAM*/ diff --git a/src/shared/platform/posix/core_eventq.c b/src/shared/platform/posix/core_eventq.c index 80119368..1146a371 100644 --- a/src/shared/platform/posix/core_eventq.c +++ b/src/shared/platform/posix/core_eventq.c @@ -9,69 +9,66 @@ #include #include -int core_eventq_init(core_eventq_t *eventq, size_t item_size, size_t max_items) -{ - eventq->buffer = core_malloc(item_size * max_items); - if (!eventq->buffer) { - return -ENOMEM; - } - eventq->item_size = item_size; - eventq->max_items = max_items; - eventq->count = 0; - eventq->head = 0; - eventq->tail = 0; - pthread_mutex_init(&eventq->mutex, NULL); - pthread_cond_init(&eventq->cond, NULL); - return 0; +int core_eventq_init(core_eventq_t *eventq, size_t item_size, size_t max_items) { + eventq->buffer = core_malloc(item_size * max_items); + if (!eventq->buffer) { + return -ENOMEM; + } + eventq->item_size = item_size; + eventq->max_items = max_items; + eventq->count = 0; + eventq->head = 0; + eventq->tail = 0; + pthread_mutex_init(&eventq->mutex, NULL); + pthread_cond_init(&eventq->cond, NULL); + return 0; } -int core_eventq_peek(core_eventq_t *eventq, void *event) -{ - pthread_mutex_lock(&eventq->mutex); - if (eventq->count == 0) { - pthread_mutex_unlock(&eventq->mutex); - return -ENOMSG; - } - memcpy(event, (char *)eventq->buffer + (eventq->head * eventq->item_size), eventq->item_size); - pthread_mutex_unlock(&eventq->mutex); - return 0; +int core_eventq_peek(core_eventq_t *eventq, void *event) { + pthread_mutex_lock(&eventq->mutex); + if (eventq->count == 0) { + pthread_mutex_unlock(&eventq->mutex); + return -ENOMSG; + } + memcpy(event, (char *)eventq->buffer + (eventq->head * eventq->item_size), eventq->item_size); + pthread_mutex_unlock(&eventq->mutex); + return 0; } -int core_eventq_get(core_eventq_t *eventq, void *event) -{ - pthread_mutex_lock(&eventq->mutex); - if (eventq->count == 0) { - pthread_mutex_unlock(&eventq->mutex); - return -ENOENT; - } - memcpy(event, (char *)eventq->buffer + (eventq->head * eventq->item_size), eventq->item_size); - eventq->head = (eventq->head + 1) % eventq->max_items; - eventq->count--; - pthread_mutex_unlock(&eventq->mutex); - return 0; +int core_eventq_get(core_eventq_t *eventq, void *event) { + pthread_mutex_lock(&eventq->mutex); + if (eventq->count == 0) { + pthread_mutex_unlock(&eventq->mutex); + return -ENOENT; + } + memcpy(event, (char *)eventq->buffer + (eventq->head * eventq->item_size), eventq->item_size); + eventq->head = (eventq->head + 1) % eventq->max_items; + eventq->count--; + pthread_mutex_unlock(&eventq->mutex); + return 0; } -int core_eventq_put(core_eventq_t *eventq, const void *event) -{ - pthread_mutex_lock(&eventq->mutex); - if (eventq->count >= eventq->max_items) { - pthread_mutex_unlock(&eventq->mutex); - return -ENOMEM; - } - memcpy((char *)eventq->buffer + (eventq->tail * eventq->item_size), event, eventq->item_size); - eventq->tail = (eventq->tail + 1) % eventq->max_items; - eventq->count++; - pthread_cond_signal(&eventq->cond); - pthread_mutex_unlock(&eventq->mutex); - return 0; +int core_eventq_put(core_eventq_t *eventq, const void *event) { + pthread_mutex_lock(&eventq->mutex); + if (eventq->count >= eventq->max_items) { + pthread_mutex_unlock(&eventq->mutex); + return -ENOMEM; + } + memcpy((char *)eventq->buffer + (eventq->tail * eventq->item_size), event, eventq->item_size); + eventq->tail = (eventq->tail + 1) % eventq->max_items; + eventq->count++; + pthread_cond_signal(&eventq->cond); + pthread_mutex_unlock(&eventq->mutex); + return 0; } -void core_eventq_destroy(core_eventq_t *eventq) -{ - pthread_mutex_destroy(&eventq->mutex); - pthread_cond_destroy(&eventq->cond); - if (eventq->buffer) { - core_free(eventq->buffer); - eventq->buffer = NULL; - } +void core_eventq_destroy(core_eventq_t *eventq) { + pthread_mutex_destroy(&eventq->mutex); + pthread_cond_destroy(&eventq->cond); + if (eventq->buffer) { + core_free(eventq->buffer); + eventq->buffer = NULL; + } } + + diff --git a/src/shared/platform/posix/core_fs.c b/src/shared/platform/posix/core_fs.c index 8881dd2c..76c2fddd 100644 --- a/src/shared/platform/posix/core_fs.c +++ b/src/shared/platform/posix/core_fs.c @@ -26,11 +26,11 @@ or as a program parameter. Encapsulation is used to avoid global variables. */ static int stored_argc = 0; -void set_argc(int argc) -{ - stored_argc = argc; +void set_argc(int argc) { + stored_argc = argc; } + /** * @brief Retrieves the stored argc value. * @@ -39,130 +39,122 @@ void set_argc(int argc) * * @return The stored argc value. */ -static int get_argc() -{ - return stored_argc; +static int get_argc() { + return stored_argc; } -int core_construct_filepath(char *path, size_t len, char *name) -{ - char cwd[PATH_MAX]; - if (getcwd(cwd, sizeof(cwd)) != NULL) { - // Shall be in /build folder - LOG_DBG("Current working dir: %s", cwd); - } - if (get_argc() > 1) { - strcpy(path, name); - return 0; - } else { - return snprintf(path, len, "%s/%s/%s.bin", cwd, APP_RESOURCE_PATH, name); - } + +int core_construct_filepath(char *path, size_t len, char *name) { + char cwd[PATH_MAX]; + if (getcwd(cwd, sizeof(cwd)) != NULL) { + // Shall be in /build folder + LOG_DBG("Current working dir: %s", cwd); + } + if (get_argc() > 1) { + strcpy(path, name); + return 0; + } else { + return snprintf(path, len, "%s/%s/%s.bin", cwd, APP_RESOURCE_PATH, name); + } } -int core_filestat(const char *path, size_t *size) -{ - struct stat st; - if (stat(path, &st) == 0) { - if (size) { - *size = st.st_size; - } - return 0; // success - } else { - return errno; // return the specific error code - } + +int core_filestat(const char *path, size_t *size) { + struct stat st; + if (stat(path, &st) == 0) { + if (size) { + *size = st.st_size; + } + return 0; // success + } else { + return errno; // return the specific error code + } + } -int core_fileopen(const char *path, void **handle) -{ - int *fd = core_malloc(sizeof(int)); - if (!fd) - return -ENOMEM; - *fd = open(path, O_RDONLY); - if (*fd < 0) { - core_free(fd); - return -errno; - } - *handle = fd; - return 0; +int core_fileopen(const char *path, void **handle) { + int *fd = core_malloc(sizeof(int)); + if (!fd) return -ENOMEM; + *fd = open(path, O_RDONLY); + if (*fd < 0) { + core_free(fd); + return -errno; + } + *handle = fd; + return 0; } -int core_fileread(void *handle, void *buffer, size_t size) -{ - int fd = *(int *)handle; - ssize_t bytes_read = read(fd, buffer, size); - if (bytes_read < 0) - return -errno; - if ((size_t)bytes_read != size) - return -EIO; - return 0; +int core_fileread(void *handle, void *buffer, size_t size) { + int fd = *(int *)handle; + ssize_t bytes_read = read(fd, buffer, size); + if (bytes_read < 0) return -errno; + if ((size_t)bytes_read != size) return -EIO; + return 0; } -int core_fileclose(void *handle) -{ - int fd = *(int *)handle; - int ret = close(fd); - core_free(handle); - return ret; +int core_fileclose(void *handle) { + int fd = *(int *)handle; + int ret = close(fd); + core_free(handle); + return ret; } -static int lsdir(const char *path) -{ - DIR *dirp; - struct dirent *entry; +static int lsdir(const char *path) { + DIR *dirp; + struct dirent *entry; - dirp = opendir(path); - if (!dirp) { - LOG_ERR("Error opening dir %s [%d]", path, errno); - return -errno; - } + dirp = opendir(path); + if (!dirp) { + LOG_ERR("Error opening dir %s [%d]", path, errno); + return -errno; + } - while ((entry = readdir(dirp)) != NULL) { - LOG_DBG("Found: %s", entry->d_name); - } + while ((entry = readdir(dirp)) != NULL) { + LOG_DBG("Found: %s", entry->d_name); + } - if (closedir(dirp) < 0) { - LOG_ERR("Error closing dir [%d]", errno); - return -errno; - } + if (closedir(dirp) < 0) { + LOG_ERR("Error closing dir [%d]", errno); + return -errno; + } - return 0; + return 0; } -void ocre_app_storage_init() -{ - struct stat st; - - if (stat(OCRE_BASE_PATH, &st) == -1) { - if (mkdir(OCRE_BASE_PATH, 0755) < 0) { - LOG_ERR("Failed to create directory %s [%d]", OCRE_BASE_PATH, errno); - } - } - - if (stat(APP_RESOURCE_PATH, &st) == -1) { - if (mkdir(APP_RESOURCE_PATH, 0755) < 0) { - LOG_ERR("Failed to create directory %s [%d]", APP_RESOURCE_PATH, errno); - } - } - - if (stat(PACKAGE_BASE_PATH, &st) == -1) { - if (mkdir(PACKAGE_BASE_PATH, 0755) < 0) { - LOG_ERR("Failed to create directory %s [%d]", PACKAGE_BASE_PATH, errno); - } - } - - if (stat(CONFIG_PATH, &st) == -1) { - if (mkdir(CONFIG_PATH, 0755) < 0) { - LOG_ERR("Failed to create directory %s [%d]", CONFIG_PATH, errno); - } - } +void ocre_app_storage_init() { + struct stat st; + + if (stat(OCRE_BASE_PATH, &st) == -1) { + if (mkdir(OCRE_BASE_PATH, 0755) < 0) { + LOG_ERR("Failed to create directory %s [%d]", OCRE_BASE_PATH, errno); + } + } + + if (stat(APP_RESOURCE_PATH, &st) == -1) { + if (mkdir(APP_RESOURCE_PATH, 0755) < 0) { + LOG_ERR("Failed to create directory %s [%d]", APP_RESOURCE_PATH, errno); + } + } + + if (stat(PACKAGE_BASE_PATH, &st) == -1) { + if (mkdir(PACKAGE_BASE_PATH, 0755) < 0) { + LOG_ERR("Failed to create directory %s [%d]", PACKAGE_BASE_PATH, errno); + } + } + + if (stat(CONFIG_PATH, &st) == -1) { + if (mkdir(CONFIG_PATH, 0755) < 0) { + LOG_ERR("Failed to create directory %s [%d]", CONFIG_PATH, errno); + } + } #ifdef CONFIG_OCRE_CONTAINER_FILESYSTEM - if (stat(CONTAINER_FS_PATH, &st) == -1) { - if (mkdir(CONTAINER_FS_PATH, 0755) < 0) { - LOG_ERR("Failed to create directory %s [%d]", CONTAINER_FS_PATH, errno); - } - } + if (stat(CONTAINER_FS_PATH, &st) == -1) { + if (mkdir(CONTAINER_FS_PATH, 0755) < 0) { + LOG_ERR("Failed to create directory %s [%d]", CONTAINER_FS_PATH, errno); + } + } #endif - lsdir(OCRE_BASE_PATH); + lsdir(OCRE_BASE_PATH); } diff --git a/src/shared/platform/posix/core_internal.h b/src/shared/platform/posix/core_internal.h index 62f69e62..0278daef 100644 --- a/src/shared/platform/posix/core_internal.h +++ b/src/shared/platform/posix/core_internal.h @@ -20,23 +20,23 @@ #include // Config macros -#define CONFIG_OCRE_CONTAINER_MESSAGING /*!< Enable container messaging support */ -#define CONFIG_OCRE_NETWORKING /*!< Enable networking support */ +#define CONFIG_OCRE_CONTAINER_MESSAGING /*!< Enable container messaging support */ +#define CONFIG_OCRE_NETWORKING /*!< Enable networking support */ #define CONFIG_OCRE_CONTAINER_FILESYSTEM #define CONFIG_OCRE_CONTAINER_WAMR_TERMINATION #define CONFIG_OCRE_TIMER // Base paths for the application -#define OCRE_BASE_PATH "./ocre_data" /*!< Base directory for Ocre resources */ +#define OCRE_BASE_PATH "./ocre_data" /*!< Base directory for Ocre resources */ -#define APP_RESOURCE_PATH OCRE_BASE_PATH "/images" /*!< Path to container images */ -#define PACKAGE_BASE_PATH OCRE_BASE_PATH "/manifests" /*!< Path to package manifests */ -#define CONFIG_PATH OCRE_BASE_PATH "/config" /*!< Path to configuration files */ +#define APP_RESOURCE_PATH OCRE_BASE_PATH "/images" /*!< Path to container images */ +#define PACKAGE_BASE_PATH OCRE_BASE_PATH "/manifests" /*!< Path to package manifests */ +#define CONFIG_PATH OCRE_BASE_PATH "/config" /*!< Path to configuration files */ /** * @brief Path for container filesystem root */ -#define CONTAINER_FS_PATH OCRE_BASE_PATH "/cfs" +#define CONTAINER_FS_PATH OCRE_BASE_PATH "/cfs" /** * @brief Ignore Zephyr's log module registration on POSIX. @@ -44,13 +44,14 @@ #define LOG_MODULE_REGISTER(name, level) #define LOG_MODULE_DECLARE(name, level) + /* * @brief Log level priority definitions (highest to lowest) */ -#define APP_LOG_LEVEL_ERR 1 -#define APP_LOG_LEVEL_WRN 2 -#define APP_LOG_LEVEL_INF 3 -#define APP_LOG_LEVEL_DBG 4 +#define APP_LOG_LEVEL_ERR 1 +#define APP_LOG_LEVEL_WRN 2 +#define APP_LOG_LEVEL_INF 3 +#define APP_LOG_LEVEL_DBG 4 /* * @brief Determine the current log level based on CONFIG defines @@ -58,59 +59,51 @@ * If none specified, default to INFO level */ #if defined(CONFIG_LOG_LVL_ERR) -#define APP_CURRENT_LOG_LEVEL APP_LOG_LEVEL_ERR + #define APP_CURRENT_LOG_LEVEL APP_LOG_LEVEL_ERR #elif defined(CONFIG_LOG_LVL_WRN) -#define APP_CURRENT_LOG_LEVEL APP_LOG_LEVEL_WRN + #define APP_CURRENT_LOG_LEVEL APP_LOG_LEVEL_WRN #elif defined(CONFIG_LOG_LVL_INF) -#define APP_CURRENT_LOG_LEVEL APP_LOG_LEVEL_INF + #define APP_CURRENT_LOG_LEVEL APP_LOG_LEVEL_INF #elif defined(CONFIG_LOG_LVL_DBG) -#define APP_CURRENT_LOG_LEVEL APP_LOG_LEVEL_DBG + #define APP_CURRENT_LOG_LEVEL APP_LOG_LEVEL_DBG #else -#define APP_CURRENT_LOG_LEVEL APP_LOG_LEVEL_INF /* Default to INFO level */ + #define APP_CURRENT_LOG_LEVEL APP_LOG_LEVEL_INF /* Default to INFO level */ #endif /** * @brief Log an error message (always shown if ERR level or higher). */ #if APP_CURRENT_LOG_LEVEL >= APP_LOG_LEVEL_ERR -#define LOG_ERR(fmt, ...) printf("[ERROR] " fmt "\n", ##__VA_ARGS__) + #define LOG_ERR(fmt, ...) printf("[ERROR] " fmt "\n", ##__VA_ARGS__) #else -#define LOG_ERR(fmt, ...) \ - do { \ - } while (0) + #define LOG_ERR(fmt, ...) do { } while(0) #endif /** * @brief Log a warning message (shown if WRN level or higher). */ #if APP_CURRENT_LOG_LEVEL >= APP_LOG_LEVEL_WRN -#define LOG_WRN(fmt, ...) printf("[WARNING] " fmt "\n", ##__VA_ARGS__) + #define LOG_WRN(fmt, ...) printf("[WARNING] " fmt "\n", ##__VA_ARGS__) #else -#define LOG_WRN(fmt, ...) \ - do { \ - } while (0) + #define LOG_WRN(fmt, ...) do { } while(0) #endif /** * @brief Log an informational message (shown if INF level or higher). */ #if APP_CURRENT_LOG_LEVEL >= APP_LOG_LEVEL_INF -#define LOG_INF(fmt, ...) printf("[INFO] " fmt "\n", ##__VA_ARGS__) + #define LOG_INF(fmt, ...) printf("[INFO] " fmt "\n", ##__VA_ARGS__) #else -#define LOG_INF(fmt, ...) \ - do { \ - } while (0) + #define LOG_INF(fmt, ...) do { } while(0) #endif /** * @brief Log a debug message (shown only if DBG level). */ #if APP_CURRENT_LOG_LEVEL >= APP_LOG_LEVEL_DBG -#define LOG_DBG(fmt, ...) printf("[DEBUG] " fmt "\n", ##__VA_ARGS__) + #define LOG_DBG(fmt, ...) printf("[DEBUG] " fmt "\n", ##__VA_ARGS__) #else -#define LOG_DBG(fmt, ...) \ - do { \ - } while (0) + #define LOG_DBG(fmt, ...) do { } while(0) #endif // Constants @@ -145,23 +138,23 @@ void set_argc(int argc); * @brief Application version string. */ #ifndef APP_VERSION_STRING -#define APP_VERSION_STRING "0.0.0-dev" +#define APP_VERSION_STRING "0.0.0-dev" #endif /* APP_VERSION_STRING */ /** * @brief Default heap buffer size for WAMR (in bytes). */ -#define CONFIG_OCRE_WAMR_HEAP_BUFFER_SIZE 512000 +#define CONFIG_OCRE_WAMR_HEAP_BUFFER_SIZE 512000 /** * @brief Default heap size for a container (in bytes). */ -#define CONFIG_OCRE_CONTAINER_DEFAULT_HEAP_SIZE 4096 +#define CONFIG_OCRE_CONTAINER_DEFAULT_HEAP_SIZE 4096 /** * @brief Default stack size for a container (in bytes). */ -#define CONFIG_OCRE_CONTAINER_DEFAULT_STACK_SIZE 4096 * 16 +#define CONFIG_OCRE_CONTAINER_DEFAULT_STACK_SIZE 4096 * 16 /** * @brief Default stack size for container threads (in bytes). @@ -172,17 +165,17 @@ void set_argc(int argc); * @brief Structure representing a thread in the Ocre runtime. */ struct core_thread { - pthread_t tid; /*!< POSIX thread identifier */ - void *stack; /*!< Pointer to thread stack memory */ - size_t stack_size; /*!< Size of the thread stack */ - uint32_t user_options; /*!< User-defined options for the thread */ + pthread_t tid; /*!< POSIX thread identifier */ + void *stack; /*!< Pointer to thread stack memory */ + size_t stack_size; /*!< Size of the thread stack */ + uint32_t user_options; /*!< User-defined options for the thread */ }; /** * @brief Structure representing a mutex in the Ocre runtime. */ struct core_mutex { - pthread_mutex_t native_mutex; /*!< POSIX mutex */ + pthread_mutex_t native_mutex; /*!< POSIX mutex */ }; #define MQ_DEFAULT_PRIO 0 /*!< Default message queue priority */ @@ -191,7 +184,7 @@ struct core_mutex { * @brief Structure representing a message queue in the Ocre runtime. */ struct core_mq { - mqd_t msgq; /*!< POSIX message queue descriptor */ + mqd_t msgq; /*!< POSIX message queue descriptor */ }; /** @@ -205,37 +198,39 @@ typedef void (*core_timer_callback_t)(void *user_data); * @brief Structure representing a timer in the Ocre runtime. */ struct core_timer { - timer_t timerid; /*!< POSIX timer identifier */ - core_timer_callback_t cb; /*!< Timer callback function */ - void *user_data; /*!< User data for the callback */ + timer_t timerid; /*!< POSIX timer identifier */ + core_timer_callback_t cb; /*!< Timer callback function */ + void *user_data; /*!< User data for the callback */ }; /* Generic singly-linked list iteration macros */ -#define CONTAINER_OF(ptr, type, member) ((type *)((char *)(ptr)-offsetof(type, member))) +#define CONTAINER_OF(ptr, type, member) \ + ((type *)((char *)(ptr) - offsetof(type, member))) -#define CORE_SLIST_FOR_EACH_CONTAINER_SAFE(list, var, tmp, member) \ - for (var = (list)->head ? CONTAINER_OF((list)->head, __typeof__(*var), member) : NULL, \ - tmp = var ? (var->member.next ? CONTAINER_OF(var->member.next, __typeof__(*var), member) : NULL) : NULL; \ - var; var = tmp, \ - tmp = tmp ? (tmp->member.next ? CONTAINER_OF(tmp->member.next, __typeof__(*var), member) : NULL) : NULL) +#define CORE_SLIST_FOR_EACH_CONTAINER_SAFE(list, var, tmp, member) \ + for (var = (list)->head ? CONTAINER_OF((list)->head, __typeof__(*var), member) : NULL, \ + tmp = var ? (var->member.next ? CONTAINER_OF(var->member.next, __typeof__(*var), member) : NULL) : NULL; \ + var; \ + var = tmp, tmp = tmp ? (tmp->member.next ? CONTAINER_OF(tmp->member.next, __typeof__(*var), member) : NULL) : NULL) -#define CORE_SLIST_FOR_EACH_CONTAINER(list, var, member) \ - for (var = (list)->head ? CONTAINER_OF((list)->head, __typeof__(*var), member) : NULL; var; \ - var = var->member.next ? CONTAINER_OF(var->member.next, __typeof__(*var), member) : NULL) +#define CORE_SLIST_FOR_EACH_CONTAINER(list, var, member) \ + for (var = (list)->head ? CONTAINER_OF((list)->head, __typeof__(*var), member) : NULL; \ + var; \ + var = var->member.next ? CONTAINER_OF(var->member.next, __typeof__(*var), member) : NULL) /** * @brief Structure representing a node in a singly-linked list. */ typedef struct core_snode { - struct core_snode *next; /*!< Pointer to the next node in the list */ + struct core_snode *next; /*!< Pointer to the next node in the list */ } core_snode_t; /** * @brief Structure representing a singly-linked list for POSIX platform. */ typedef struct { - core_snode_t *head; /*!< Pointer to the first node in the list */ - core_snode_t *tail; /*!< Pointer to the last node in the list */ + core_snode_t *head; /*!< Pointer to the first node in the list */ + core_snode_t *tail; /*!< Pointer to the last node in the list */ } core_slist_t; /** @@ -266,7 +261,7 @@ void core_slist_remove(core_slist_t *list, core_snode_t *prev, core_snode_t *nod * @brief Spinlock type for POSIX platform (simulated using mutex). */ typedef struct { - pthread_mutex_t mutex; /*!< POSIX mutex for spinlock simulation */ + pthread_mutex_t mutex; /*!< POSIX mutex for spinlock simulation */ } core_spinlock_t; /** @@ -276,19 +271,19 @@ typedef int core_spinlock_key_t; /** * @brief Generic event queue structure for POSIX platform. - * + * * A thread-safe circular buffer implementation that can store * any type of data items with configurable size and capacity. */ typedef struct { - void *buffer; /*!< Dynamically allocated buffer for queue items */ - size_t item_size; /*!< Size of each individual item in bytes */ - size_t max_items; /*!< Maximum number of items the queue can hold */ - size_t count; /*!< Current number of items in the queue */ - size_t head; /*!< Index of the next item to be read */ - size_t tail; /*!< Index where the next item will be written */ - pthread_mutex_t mutex; /*!< Mutex for thread-safe access */ - pthread_cond_t cond; /*!< Condition variable for signaling */ + void *buffer; /*!< Dynamically allocated buffer for queue items */ + size_t item_size; /*!< Size of each individual item in bytes */ + size_t max_items; /*!< Maximum number of items the queue can hold */ + size_t count; /*!< Current number of items in the queue */ + size_t head; /*!< Index of the next item to be read */ + size_t tail; /*!< Index where the next item will be written */ + pthread_mutex_t mutex; /*!< Mutex for thread-safe access */ + pthread_cond_t cond; /*!< Condition variable for signaling */ } core_eventq_t; #endif /* OCRE_CORE_INTERNAL_H */ diff --git a/src/shared/platform/posix/core_memory.c b/src/shared/platform/posix/core_memory.c index 33203b06..0e13a8c0 100644 --- a/src/shared/platform/posix/core_memory.c +++ b/src/shared/platform/posix/core_memory.c @@ -9,12 +9,10 @@ #include -void *core_malloc(size_t size) -{ - return malloc(size); +void *core_malloc(size_t size) { + return malloc(size); } -void core_free(void *ptr) -{ - free(ptr); +void core_free(void *ptr) { + free(ptr); } diff --git a/src/shared/platform/posix/core_misc.c b/src/shared/platform/posix/core_misc.c index 922ee62c..069c1735 100644 --- a/src/shared/platform/posix/core_misc.c +++ b/src/shared/platform/posix/core_misc.c @@ -8,52 +8,49 @@ #include "ocre_core_external.h" #include -#include +#include #include #include void core_sleep_ms(int milliseconds) { - struct timespec ts; - int res; - - if (milliseconds < 0) { - errno = EINVAL; - fprintf(stderr, "core_sleep_ms: Invalid milliseconds value (%d)\n", milliseconds); - return; - } - - ts.tv_sec = milliseconds / 1000; - ts.tv_nsec = (milliseconds % 1000) * 1000000; - - do { - res = nanosleep(&ts, &ts); - if (res && errno != EINTR) { - fprintf(stderr, "core_sleep_ms: nanosleep failed (errno=%d)\n", errno); - } - } while (res && errno == EINTR); + struct timespec ts; + int res; + + if (milliseconds < 0) + { + errno = EINVAL; + fprintf(stderr, "core_sleep_ms: Invalid milliseconds value (%d)\n", milliseconds); + return; + } + + ts.tv_sec = milliseconds / 1000; + ts.tv_nsec = (milliseconds % 1000) * 1000000; + + do { + res = nanosleep(&ts, &ts); + if (res && errno != EINTR) { + fprintf(stderr, "core_sleep_ms: nanosleep failed (errno=%d)\n", errno); + } + } while (res && errno == EINTR); } -void core_yield(void) -{ - sched_yield(); +void core_yield(void) { + sched_yield(); } -uint32_t core_uptime_get(void) -{ - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return (uint32_t)(ts.tv_sec * 1000 + ts.tv_nsec / 1000000); +uint32_t core_uptime_get(void) { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return (uint32_t)(ts.tv_sec * 1000 + ts.tv_nsec / 1000000); } -core_spinlock_key_t core_spinlock_lock(core_spinlock_t *lock) -{ - pthread_mutex_lock(&lock->mutex); - return 0; +core_spinlock_key_t core_spinlock_lock(core_spinlock_t *lock) { + pthread_mutex_lock(&lock->mutex); + return 0; } -void core_spinlock_unlock(core_spinlock_t *lock, core_spinlock_key_t key) -{ - (void)key; - pthread_mutex_unlock(&lock->mutex); +void core_spinlock_unlock(core_spinlock_t *lock, core_spinlock_key_t key) { + (void)key; + pthread_mutex_unlock(&lock->mutex); } diff --git a/src/shared/platform/posix/core_mq.c b/src/shared/platform/posix/core_mq.c index 85a7d77a..e9afa8c8 100644 --- a/src/shared/platform/posix/core_mq.c +++ b/src/shared/platform/posix/core_mq.c @@ -12,53 +12,54 @@ int core_mq_init(core_mq_t *mq, const char *name, size_t msg_size, uint32_t max_msgs) { - struct mq_attr attr; + struct mq_attr attr; - // Configure the message queue attributes - attr.mq_flags = 0; // Blocking mode - attr.mq_maxmsg = max_msgs; // Maximum number of messages in the queue - attr.mq_msgsize = msg_size; // Size of each message - attr.mq_curmsgs = 0; // Number of messages currently in the queue + // Configure the message queue attributes + attr.mq_flags = 0; // Blocking mode + attr.mq_maxmsg = max_msgs; // Maximum number of messages in the queue + attr.mq_msgsize = msg_size; // Size of each message + attr.mq_curmsgs = 0; // Number of messages currently in the queue - // Try to unlink the message queue, but ignore error if it doesn't exist - if (mq_unlink(name) == -1 && errno != ENOENT) { - perror("Main: mq_unlink"); - return -errno; - } + // Try to unlink the message queue, but ignore error if it doesn't exist + if (mq_unlink(name) == -1 && errno != ENOENT) + { + perror("Main: mq_unlink"); + return -errno; + } - // Create the message queue - mq->msgq = mq_open(name, O_CREAT | O_RDWR, 0644, &attr); - if (mq->msgq == (mqd_t)-1) { - perror("Failed to create message queue"); - return -errno; - } - return 0; + // Create the message queue + mq->msgq = mq_open(name, O_CREAT | O_RDWR, 0644, &attr); + if (mq->msgq == (mqd_t)-1) { + perror("Failed to create message queue"); + return -errno; + } + return 0; } int core_mq_send(core_mq_t *mq, const void *data, size_t msg_len) { - int ret = mq_send(mq->msgq, (const char *)data, msg_len, MQ_DEFAULT_PRIO); + int ret = mq_send(mq->msgq, (const char *)data, msg_len, MQ_DEFAULT_PRIO); - if (ret == -1) { - perror("Failed to send message"); - } - return ret; + if (ret == -1) { + perror("Failed to send message"); + } + return ret; } int core_mq_recv(core_mq_t *mq, void *data) { - struct mq_attr attr; - unsigned int priority; + struct mq_attr attr; + unsigned int priority; - // Get message queue attributes - if (mq_getattr(mq->msgq, &attr) == -1) { - perror("Failed to get message queue attributes"); - return -errno; - } - ssize_t bytes_received = mq_receive(mq->msgq, (char *)data, attr.mq_msgsize, &priority); - if (bytes_received == -1) { - perror("Failed to receive message"); - return -errno; - } - return bytes_received; + // Get message queue attributes + if (mq_getattr(mq->msgq, &attr) == -1) { + perror("Failed to get message queue attributes"); + return -errno; + } + ssize_t bytes_received = mq_receive(mq->msgq, (char *)data, attr.mq_msgsize, &priority); + if (bytes_received == -1) { + perror("Failed to receive message"); + return -errno; + } + return bytes_received; } diff --git a/src/shared/platform/posix/core_mutex.c b/src/shared/platform/posix/core_mutex.c index 36d20f99..a13753da 100644 --- a/src/shared/platform/posix/core_mutex.c +++ b/src/shared/platform/posix/core_mutex.c @@ -9,24 +9,19 @@ #include #include -int core_mutex_init(core_mutex_t *mutex) -{ - if (!mutex) - return -1; - return pthread_mutex_init(&mutex->native_mutex, NULL); +int core_mutex_init(core_mutex_t *mutex) { + if (!mutex) return -1; + return pthread_mutex_init(&mutex->native_mutex, NULL); } -int core_mutex_destroy(core_mutex_t *mutex) -{ - return pthread_mutex_destroy(&mutex->native_mutex); +int core_mutex_destroy(core_mutex_t *mutex) { + return pthread_mutex_destroy(&mutex->native_mutex); } -int core_mutex_lock(core_mutex_t *mutex) -{ - return pthread_mutex_lock(&mutex->native_mutex); +int core_mutex_lock(core_mutex_t *mutex) { + return pthread_mutex_lock(&mutex->native_mutex); } -int core_mutex_unlock(core_mutex_t *mutex) -{ - return pthread_mutex_unlock(&mutex->native_mutex); +int core_mutex_unlock(core_mutex_t *mutex) { + return pthread_mutex_unlock(&mutex->native_mutex); } diff --git a/src/shared/platform/posix/core_slist.c b/src/shared/platform/posix/core_slist.c index 81311908..1def4404 100644 --- a/src/shared/platform/posix/core_slist.c +++ b/src/shared/platform/posix/core_slist.c @@ -7,31 +7,28 @@ #include "ocre_core_external.h" -void core_slist_init(core_slist_t *list) -{ - list->head = NULL; - list->tail = NULL; +void core_slist_init(core_slist_t *list) { + list->head = NULL; + list->tail = NULL; } -void core_slist_append(core_slist_t *list, core_snode_t *node) -{ - node->next = NULL; - if (list->tail) { - list->tail->next = node; - } else { - list->head = node; - } - list->tail = node; +void core_slist_append(core_slist_t *list, core_snode_t *node) { + node->next = NULL; + if (list->tail) { + list->tail->next = node; + } else { + list->head = node; + } + list->tail = node; } -void core_slist_remove(core_slist_t *list, core_snode_t *prev, core_snode_t *node) -{ - if (prev) { - prev->next = node->next; - } else { - list->head = node->next; - } - if (list->tail == node) { - list->tail = prev; - } +void core_slist_remove(core_slist_t *list, core_snode_t *prev, core_snode_t *node) { + if (prev) { + prev->next = node->next; + } else { + list->head = node->next; + } + if (list->tail == node) { + list->tail = prev; + } } diff --git a/src/shared/platform/posix/core_thread.c b/src/shared/platform/posix/core_thread.c index 6052beeb..f6763e5b 100644 --- a/src/shared/platform/posix/core_thread.c +++ b/src/shared/platform/posix/core_thread.c @@ -13,70 +13,65 @@ #include #include -static void *thread_entry(void *arg) -{ - struct { - core_thread_func_t func; - void *user_arg; - char name[16]; - } *entry = arg; - if (entry->name[0]) - pthread_setname_np(pthread_self(), entry->name); +static void *thread_entry(void *arg) { + struct { + core_thread_func_t func; + void *user_arg; + char name[16]; + } *entry = arg; - entry->func(entry->user_arg); - free(entry); - return NULL; + if (entry->name[0]) + pthread_setname_np(pthread_self(), entry->name); + + entry->func(entry->user_arg); + free(entry); + return NULL; } -int core_thread_create(core_thread_t *thread, core_thread_func_t func, void *arg, const char *name, size_t stack_size, - int priority) -{ - if (!thread || !func) - return -1; - pthread_attr_t attr; - int ret; +int core_thread_create(core_thread_t *thread, core_thread_func_t func, void *arg, const char *name, size_t stack_size, int priority) { + if (!thread || !func) return -1; + pthread_attr_t attr; + int ret; - if (stack_size < PTHREAD_STACK_MIN) { - fprintf(stderr, "STACK_SIZE must be at least PTHREAD_STACK_MIN (%zu)\n", (size_t)PTHREAD_STACK_MIN); - return -1; - } + if (stack_size < PTHREAD_STACK_MIN) { + fprintf(stderr, "STACK_SIZE must be at least PTHREAD_STACK_MIN (%zu)\n", (size_t)PTHREAD_STACK_MIN); + return -1; + } - thread->stack_size = stack_size; - if (posix_memalign(&thread->stack, sysconf(_SC_PAGESIZE), stack_size) != 0) { - perror("posix_memalign"); - return -1; - } + thread->stack_size = stack_size; + if (posix_memalign(&thread->stack, sysconf(_SC_PAGESIZE), stack_size) != 0) { + perror("posix_memalign"); + return -1; + } - pthread_attr_init(&attr); - pthread_attr_setstack(&attr, thread->stack, stack_size); + pthread_attr_init(&attr); + pthread_attr_setstack(&attr, thread->stack, stack_size); - // Prepare entry struct for name passing - struct { - core_thread_func_t func; - void *user_arg; - char name[16]; - } *entry = malloc(sizeof(*entry)); - entry->func = func; - entry->user_arg = arg; - strncpy(entry->name, name ? name : "", sizeof(entry->name) - 1); - entry->name[sizeof(entry->name) - 1] = '\0'; + // Prepare entry struct for name passing + struct { + core_thread_func_t func; + void *user_arg; + char name[16]; + } *entry = malloc(sizeof(*entry)); + entry->func = func; + entry->user_arg = arg; + strncpy(entry->name, name ? name : "", sizeof(entry->name) - 1); + entry->name[sizeof(entry->name) - 1] = '\0'; - ret = pthread_create(&thread->tid, &attr, thread_entry, entry); - pthread_attr_destroy(&attr); - if (ret != 0) { - free(thread->stack); - free(entry); - return -1; - } - return 0; + ret = pthread_create(&thread->tid, &attr, thread_entry, entry); + pthread_attr_destroy(&attr); + if (ret != 0) { + free(thread->stack); + free(entry); + return -1; + } + return 0; } -void core_thread_destroy(core_thread_t *thread) -{ - if (!thread) - return; - pthread_cancel(thread->tid); - pthread_join(thread->tid, NULL); - free(thread->stack); +void core_thread_destroy(core_thread_t *thread) { + if (!thread) return; + pthread_cancel(thread->tid); + pthread_join(thread->tid, NULL); + free(thread->stack); } diff --git a/src/shared/platform/posix/core_timer.c b/src/shared/platform/posix/core_timer.c index 33e38307..0692de34 100644 --- a/src/shared/platform/posix/core_timer.c +++ b/src/shared/platform/posix/core_timer.c @@ -12,48 +12,41 @@ #include #include -static void posix_timer_cb(union sigval sv) -{ - core_timer_t *timer = (core_timer_t *)sv.sival_ptr; - if (timer->cb) { - timer->cb(timer->user_data); - } +static void posix_timer_cb(union sigval sv) { + core_timer_t *timer = (core_timer_t *)sv.sival_ptr; + if (timer->cb) { + timer->cb(timer->user_data); + } } -int core_timer_init(core_timer_t *timer, core_timer_callback_t cb, void *user_data) -{ - if (!timer) - return -1; - struct sigevent sev = {0}; - timer->cb = cb; - timer->user_data = user_data; - sev.sigev_notify = SIGEV_THREAD; - sev.sigev_notify_function = posix_timer_cb; - sev.sigev_value.sival_ptr = timer; - return timer_create(CLOCK_REALTIME, &sev, &timer->timerid); +int core_timer_init(core_timer_t *timer, core_timer_callback_t cb, void *user_data) { + if (!timer) return -1; + struct sigevent sev = {0}; + timer->cb = cb; + timer->user_data = user_data; + sev.sigev_notify = SIGEV_THREAD; + sev.sigev_notify_function = posix_timer_cb; + sev.sigev_value.sival_ptr = timer; + return timer_create(CLOCK_REALTIME, &sev, &timer->timerid); } -int core_timer_start(core_timer_t *timer, int timeout_ms, int period_ms) -{ - if (!timer) - return -1; - struct itimerspec its; - if (timeout_ms == 0 && period_ms > 0) { - its.it_value.tv_sec = period_ms / 1000; - its.it_value.tv_nsec = (period_ms % 1000) * 1000000; - } else { - its.it_value.tv_sec = timeout_ms / 1000; - its.it_value.tv_nsec = (timeout_ms % 1000) * 1000000; - } - its.it_interval.tv_sec = period_ms / 1000; - its.it_interval.tv_nsec = (period_ms % 1000) * 1000000; - return timer_settime(timer->timerid, 0, &its, NULL); +int core_timer_start(core_timer_t *timer, int timeout_ms, int period_ms) { + if (!timer) return -1; + struct itimerspec its; + if (timeout_ms == 0 && period_ms > 0) { + its.it_value.tv_sec = period_ms / 1000; + its.it_value.tv_nsec = (period_ms % 1000) * 1000000; + } else { + its.it_value.tv_sec = timeout_ms / 1000; + its.it_value.tv_nsec = (timeout_ms % 1000) * 1000000; + } + its.it_interval.tv_sec = period_ms / 1000; + its.it_interval.tv_nsec = (period_ms % 1000) * 1000000; + return timer_settime(timer->timerid, 0, &its, NULL); } -int core_timer_stop(core_timer_t *timer) -{ - if (!timer) - return -1; - struct itimerspec its = {0}; - return timer_settime(timer->timerid, 0, &its, NULL); +int core_timer_stop(core_timer_t *timer) { + if (!timer) return -1; + struct itimerspec its = {0}; + return timer_settime(timer->timerid, 0, &its, NULL); } diff --git a/src/shared/platform/zephyr/core_eventq.c b/src/shared/platform/zephyr/core_eventq.c index fd0a30e0..7ec83f7a 100644 --- a/src/shared/platform/zephyr/core_eventq.c +++ b/src/shared/platform/zephyr/core_eventq.c @@ -9,59 +9,56 @@ #include #include -int core_eventq_init(core_eventq_t *eventq, size_t item_size, size_t max_items) -{ - eventq->buffer = core_malloc(item_size * max_items); - if (!eventq->buffer) { - return -ENOMEM; - } - eventq->item_size = item_size; - eventq->max_items = max_items; - - k_msgq_init(&eventq->msgq, (char *)eventq->buffer, item_size, max_items); - return 0; +int core_eventq_init(core_eventq_t *eventq, size_t item_size, size_t max_items) { + eventq->buffer = core_malloc(item_size * max_items); + if (!eventq->buffer) { + return -ENOMEM; + } + eventq->item_size = item_size; + eventq->max_items = max_items; + + k_msgq_init(&eventq->msgq, (char *)eventq->buffer, item_size, max_items); + return 0; } -int core_eventq_peek(core_eventq_t *eventq, void *event) -{ - int ret = k_msgq_peek(&eventq->msgq, event); - if (ret == 0) { - return 0; - } else if (ret == -ENOMSG) { - return -ENOMSG; - } else { - return ret; - } +int core_eventq_peek(core_eventq_t *eventq, void *event) { + int ret = k_msgq_peek(&eventq->msgq, event); + if (ret == 0) { + return 0; + } else if (ret == -ENOMSG) { + return -ENOMSG; + } else { + return ret; + } } -int core_eventq_get(core_eventq_t *eventq, void *event) -{ - int ret = k_msgq_get(&eventq->msgq, event, K_NO_WAIT); - if (ret == 0) { - return 0; - } else if (ret == -ENOMSG) { - return -ENOENT; - } else { - return ret; - } +int core_eventq_get(core_eventq_t *eventq, void *event) { + int ret = k_msgq_get(&eventq->msgq, event, K_NO_WAIT); + if (ret == 0) { + return 0; + } else if (ret == -ENOMSG) { + return -ENOENT; + } else { + return ret; + } } -int core_eventq_put(core_eventq_t *eventq, const void *event) -{ - int ret = k_msgq_put(&eventq->msgq, event, K_NO_WAIT); - if (ret == 0) { - return 0; - } else if (ret == -ENOMSG) { - return -ENOMEM; - } else { - return ret; - } +int core_eventq_put(core_eventq_t *eventq, const void *event) { + int ret = k_msgq_put(&eventq->msgq, event, K_NO_WAIT); + if (ret == 0) { + return 0; + } else if (ret == -ENOMSG) { + return -ENOMEM; + } else { + return ret; + } } -void core_eventq_destroy(core_eventq_t *eventq) -{ - if (eventq->buffer) { - core_free(eventq->buffer); - eventq->buffer = NULL; - } +void core_eventq_destroy(core_eventq_t *eventq) { + if (eventq->buffer) { + core_free(eventq->buffer); + eventq->buffer = NULL; + } } + + diff --git a/src/shared/platform/zephyr/core_fs.c b/src/shared/platform/zephyr/core_fs.c index 8e480ccf..ef08a6de 100644 --- a/src/shared/platform/zephyr/core_fs.c +++ b/src/shared/platform/zephyr/core_fs.c @@ -23,119 +23,111 @@ LOG_MODULE_REGISTER(filesystem, OCRE_LOG_LEVEL); #ifdef CONFIG_SHELL #define print(shell, level, fmt, ...) \ - do { \ - shell_fprintf(shell, level, fmt, ##__VA_ARGS__); \ - } while (false) + do { \ + shell_fprintf(shell, level, fmt, ##__VA_ARGS__); \ + } while (false) #else #define print(shell, level, fmt, ...) \ - do { \ - printk(fmt, ##__VA_ARGS__); \ - } while (false) + do { \ + printk(fmt, ##__VA_ARGS__); \ + } while (false) #endif -int core_construct_filepath(char *path, size_t len, char *name) -{ - return snprintf(path, len, "/lfs/ocre/images/%s.bin", name); +int core_construct_filepath(char *path, size_t len, char *name) { + return snprintf(path, len, "/lfs/ocre/images/%s.bin", name); } -int core_filestat(const char *path, size_t *size) -{ - struct fs_dirent entry; - int ret = fs_stat(path, &entry); - if (ret == 0 && size) { - *size = entry.size; - } - return ret; +int core_filestat(const char *path, size_t *size) { + struct fs_dirent entry; + int ret = fs_stat(path, &entry); + if (ret == 0 && size) { + *size = entry.size; + } + return ret; } -int core_fileopen(const char *path, void **handle) -{ - struct fs_file_t *file = core_malloc(sizeof(struct fs_file_t)); - if (!file) - return -ENOMEM; - fs_file_t_init(file); - int ret = fs_open(file, path, FS_O_READ); - if (ret < 0) { - core_free(file); - return ret; - } - *handle = file; - return 0; +int core_fileopen(const char *path, void **handle) { + struct fs_file_t *file = core_malloc(sizeof(struct fs_file_t)); + if (!file) return -ENOMEM; + fs_file_t_init(file); + int ret = fs_open(file, path, FS_O_READ); + if (ret < 0) { + core_free(file); + return ret; + } + *handle = file; + return 0; } -int core_fileread(void *handle, void *buffer, size_t size) -{ - struct fs_file_t *file = (struct fs_file_t *)handle; - return fs_read(file, buffer, size); +int core_fileread(void *handle, void *buffer, size_t size) { + struct fs_file_t *file = (struct fs_file_t *)handle; + return fs_read(file, buffer, size); } -int core_fileclose(void *handle) -{ - struct fs_file_t *file = (struct fs_file_t *)handle; - int ret = fs_close(file); - core_free(file); - return ret; +int core_fileclose(void *handle) { + struct fs_file_t *file = (struct fs_file_t *)handle; + int ret = fs_close(file); + core_free(file); + return ret; } -static int lsdir(const char *path) -{ - int res; - struct fs_dir_t dirp; - static struct fs_dirent entry; - - fs_dir_t_init(&dirp); - - /* Verify fs_opendir() */ - res = fs_opendir(&dirp, path); - if (res) { - LOG_ERR("Error opening dir %s [%d]\n", path, res); - return res; - } - - for (;;) { - // Verify fs_readdir() - res = fs_readdir(&dirp, &entry); - - // entry.name[0] == 0 means end-of-dir - if (res || entry.name[0] == 0) { - if (res < 0) { - LOG_ERR("Error reading dir [%d]\n", res); - } - break; - } - } - - // Verify fs_closedir() - fs_closedir(&dirp); - - return res; +static int lsdir(const char *path) { + int res; + struct fs_dir_t dirp; + static struct fs_dirent entry; + + fs_dir_t_init(&dirp); + + /* Verify fs_opendir() */ + res = fs_opendir(&dirp, path); + if (res) { + LOG_ERR("Error opening dir %s [%d]\n", path, res); + return res; + } + + for (;;) { + // Verify fs_readdir() + res = fs_readdir(&dirp, &entry); + + // entry.name[0] == 0 means end-of-dir + if (res || entry.name[0] == 0) { + if (res < 0) { + LOG_ERR("Error reading dir [%d]\n", res); + } + break; + } + } + + // Verify fs_closedir() + fs_closedir(&dirp); + + return res; } -static int littlefs_flash_erase(unsigned int id) -{ - const struct flash_area *pfa; - int rc; +static int littlefs_flash_erase(unsigned int id) { + const struct flash_area *pfa; + int rc; - rc = flash_area_open(id, &pfa); - if (rc < 0) { - LOG_ERR("FAIL: unable to find flash area %u: %d\n", id, rc); - return rc; - } + rc = flash_area_open(id, &pfa); + if (rc < 0) { + LOG_ERR("FAIL: unable to find flash area %u: %d\n", id, rc); + return rc; + } - LOG_PRINTK("Area %u at 0x%x on %s for %u bytes\n", id, (unsigned int)pfa->fa_off, pfa->fa_dev->name, - (unsigned int)pfa->fa_size); + LOG_PRINTK("Area %u at 0x%x on %s for %u bytes\n", id, (unsigned int)pfa->fa_off, pfa->fa_dev->name, + (unsigned int)pfa->fa_size); - rc = flash_area_erase(pfa, 0, pfa->fa_size); + rc = flash_area_erase(pfa, 0, pfa->fa_size); - if (rc < 0) { - LOG_ERR("Failed to erase flash: %d", rc); - } else { - LOG_INF("Successfully erased flash"); - } + if (rc < 0) { + LOG_ERR("Failed to erase flash: %d", rc); + } else { + LOG_INF("Successfully erased flash"); + } - flash_area_close(pfa); + flash_area_close(pfa); - return rc; + return rc; } #define PARTITION_NODE DT_NODELABEL(lfs1) @@ -145,138 +137,134 @@ FS_FSTAB_DECLARE_ENTRY(PARTITION_NODE); #else /* PARTITION_NODE */ FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(user_data); static struct fs_mount_t lfs_storage_mnt = { - .type = FS_LITTLEFS, - .fs_data = &user_data, - .storage_dev = (void *)FIXED_PARTITION_ID(user_data_partition), - .mnt_point = FS_MOUNT_POINT, + .type = FS_LITTLEFS, + .fs_data = &user_data, + .storage_dev = (void *)FIXED_PARTITION_ID(user_data_partition), + .mnt_point = FS_MOUNT_POINT, }; #endif /* PARTITION_NODE */ struct fs_mount_t *mp = #if DT_NODE_EXISTS(PARTITION_NODE) - &FS_FSTAB_ENTRY(PARTITION_NODE) + &FS_FSTAB_ENTRY(PARTITION_NODE) #else - &lfs_storage_mnt + &lfs_storage_mnt #endif - ; + ; -static int littlefs_mount(struct fs_mount_t *mp) -{ - int rc = 0; +static int littlefs_mount(struct fs_mount_t *mp) { + int rc = 0; - /* Do not mount if auto-mount has been enabled */ + /* Do not mount if auto-mount has been enabled */ #if !DT_NODE_EXISTS(PARTITION_NODE) || !(FSTAB_ENTRY_DT_MOUNT_FLAGS(PARTITION_NODE) & FS_MOUNT_FLAG_AUTOMOUNT) - rc = fs_mount(mp); - if (rc < 0) { - LOG_ERR("FAIL: mount id %" PRIuPTR " at %s: %d\n", (uintptr_t)mp->storage_dev, mp->mnt_point, rc); - return rc; - } - LOG_INF("%s mount: %d\n", mp->mnt_point, rc); + rc = fs_mount(mp); + if (rc < 0) { + LOG_ERR("FAIL: mount id %" PRIuPTR " at %s: %d\n", (uintptr_t)mp->storage_dev, mp->mnt_point, rc); + return rc; + } + LOG_INF("%s mount: %d\n", mp->mnt_point, rc); #else - LOG_INF("%s automounted\n", mp->mnt_point); + LOG_INF("%s automounted\n", mp->mnt_point); #endif - return rc; + return rc; } #ifdef CONFIG_APP_LITTLEFS_STORAGE_BLK_SDMMC struct fs_littlefs lfsfs; static struct fs_mount_t __mp = { - .type = FS_LITTLEFS, - .fs_data = &lfsfs, - .flags = FS_MOUNT_FLAG_USE_DISK_ACCESS, + .type = FS_LITTLEFS, + .fs_data = &lfsfs, + .flags = FS_MOUNT_FLAG_USE_DISK_ACCESS, }; struct fs_mount_t *mp = &__mp; -static int littlefs_mount(struct fs_mount_t *mp) -{ - static const char *disk_mount_pt = "/" CONFIG_SDMMC_VOLUME_NAME ":"; - static const char *disk_pdrv = CONFIG_SDMMC_VOLUME_NAME; +static int littlefs_mount(struct fs_mount_t *mp) { + static const char *disk_mount_pt = "/" CONFIG_SDMMC_VOLUME_NAME ":"; + static const char *disk_pdrv = CONFIG_SDMMC_VOLUME_NAME; - mp->storage_dev = (void *)disk_pdrv; - mp->mnt_point = disk_mount_pt; + mp->storage_dev = (void *)disk_pdrv; + mp->mnt_point = disk_mount_pt; - return fs_mount(mp); + return fs_mount(mp); } #endif /* CONFIG_APP_LITTLEFS_STORAGE_BLK_SDMMC */ -void ocre_app_storage_init() -{ - struct fs_dirent entry; - struct fs_statvfs sbuf; - int rc; - - rc = littlefs_mount(mp); - if (rc < 0) { - return; - } - - rc = fs_statvfs(mp->mnt_point, &sbuf); - if (rc < 0) { - LOG_ERR("FAILR statvfs: %d", rc); - return; - } - - LOG_DBG("%s: bsize = %lu ; frsize = %lu ;" - " blocks = %lu ; bfree = %lu", - mp->mnt_point, sbuf.f_bsize, sbuf.f_frsize, sbuf.f_blocks, sbuf.f_bfree); - - rc = lsdir(mp->mnt_point); - if (rc < 0) { - LOG_ERR("FAIL: lsdir %s: %d", mp->mnt_point, rc); - } - - // Create the core directories if they don't exist - if (fs_stat(OCRE_BASE_PATH, &entry) == -ENOENT) { - fs_mkdir(OCRE_BASE_PATH); - } - - if (fs_stat(APP_RESOURCE_PATH, &entry) == -ENOENT) { - fs_mkdir(APP_RESOURCE_PATH); - } - - if (fs_stat(PACKAGE_BASE_PATH, &entry) == -ENOENT) { - fs_mkdir(PACKAGE_BASE_PATH); - } - - if (fs_stat(CONFIG_PATH, &entry) == -ENOENT) { - fs_mkdir(CONFIG_PATH); - } +void ocre_app_storage_init() { + struct fs_dirent entry; + struct fs_statvfs sbuf; + int rc; + + rc = littlefs_mount(mp); + if (rc < 0) { + return; + } + + rc = fs_statvfs(mp->mnt_point, &sbuf); + if (rc < 0) { + LOG_ERR("FAILR statvfs: %d", rc); + return; + } + + LOG_DBG("%s: bsize = %lu ; frsize = %lu ;" + " blocks = %lu ; bfree = %lu", + mp->mnt_point, sbuf.f_bsize, sbuf.f_frsize, sbuf.f_blocks, sbuf.f_bfree); + + rc = lsdir(mp->mnt_point); + if (rc < 0) { + LOG_ERR("FAIL: lsdir %s: %d", mp->mnt_point, rc); + } + + // Create the core directories if they don't exist + if (fs_stat(OCRE_BASE_PATH, &entry) == -ENOENT) { + fs_mkdir(OCRE_BASE_PATH); + } + + if (fs_stat(APP_RESOURCE_PATH, &entry) == -ENOENT) { + fs_mkdir(APP_RESOURCE_PATH); + } + + if (fs_stat(PACKAGE_BASE_PATH, &entry) == -ENOENT) { + fs_mkdir(PACKAGE_BASE_PATH); + } + + if (fs_stat(CONFIG_PATH, &entry) == -ENOENT) { + fs_mkdir(CONFIG_PATH); + } #ifdef CONFIG_OCRE_CONTAINER_FILESYSTEM - if (fs_stat(CONTAINER_FS_PATH, &entry) == -ENOENT) { - fs_mkdir(CONTAINER_FS_PATH); - } + if (fs_stat(CONTAINER_FS_PATH, &entry) == -ENOENT) { + fs_mkdir(CONTAINER_FS_PATH); + } #endif } -static int cmd_flash_format(const struct shell *shell, size_t argc, char *argv[]) -{ - int rc; - fs_unmount(mp); +static int cmd_flash_format(const struct shell *shell, size_t argc, char *argv[]) { + int rc; + fs_unmount(mp); - // FIXME: if erasing the whole chip, could cause problems - // https://github.com/zephyrproject-rtos/zephyr/issues/56442 - rc = littlefs_flash_erase((uintptr_t)mp->storage_dev); + // FIXME: if erasing the whole chip, could cause problems + // https://github.com/zephyrproject-rtos/zephyr/issues/56442 + rc = littlefs_flash_erase((uintptr_t)mp->storage_dev); - if (rc < 0) { - print(shell, SHELL_WARNING, "Format failed: %d\n", rc); - } else { - print(shell, SHELL_NORMAL, "Format succeeded\n"); - } + if (rc < 0) { + print(shell, SHELL_WARNING, "Format failed: %d\n", rc); + } else { + print(shell, SHELL_NORMAL, "Format succeeded\n"); + } - if (rc == 0) { - LOG_INF("Mounting..."); - rc = littlefs_mount(mp); - } + if (rc == 0) { + LOG_INF("Mounting..."); + rc = littlefs_mount(mp); + } - return rc; + return rc; } SHELL_STATIC_SUBCMD_SET_CREATE(flash_commands, - SHELL_CMD(format, NULL, "Format the flash storage device (all user data will be lost)", - cmd_flash_format), - SHELL_SUBCMD_SET_END); + SHELL_CMD(format, NULL, "Format the flash storage device (all user data will be lost)", + cmd_flash_format), + SHELL_SUBCMD_SET_END); SHELL_CMD_REGISTER(user_storage, &flash_commands, "User storage management", NULL); diff --git a/src/shared/platform/zephyr/core_memory.c b/src/shared/platform/zephyr/core_memory.c index f862143c..3655ed4b 100644 --- a/src/shared/platform/zephyr/core_memory.c +++ b/src/shared/platform/zephyr/core_memory.c @@ -9,12 +9,10 @@ #include -void *core_malloc(size_t size) -{ - return k_malloc(size); +void *core_malloc(size_t size) { + return k_malloc(size); } -void core_free(void *ptr) -{ - k_free(ptr); +void core_free(void *ptr) { + k_free(ptr); } diff --git a/src/shared/platform/zephyr/core_misc.c b/src/shared/platform/zephyr/core_misc.c index 7bef689f..c689ee77 100644 --- a/src/shared/platform/zephyr/core_misc.c +++ b/src/shared/platform/zephyr/core_misc.c @@ -8,12 +8,10 @@ #include "ocre_core_external.h" #include -void core_sleep_ms(int milliseconds) -{ - k_msleep(milliseconds); +void core_sleep_ms(int milliseconds) { + k_msleep(milliseconds); } -void core_yield(void) -{ - k_yield(); +void core_yield(void) { + k_yield(); } diff --git a/src/shared/platform/zephyr/core_mq.c b/src/shared/platform/zephyr/core_mq.c index 2e1589df..c7c88665 100644 --- a/src/shared/platform/zephyr/core_mq.c +++ b/src/shared/platform/zephyr/core_mq.c @@ -11,22 +11,22 @@ LOG_MODULE_DECLARE(platform_mq_component, OCRE_LOG_LEVEL); int core_mq_init(core_mq_t *mq, const char *name, size_t msg_size, uint32_t max_msgs) { - mq->msgq_buffer = k_malloc(msg_size * max_msgs); - k_msgq_init(&mq->msgq, mq->msgq_buffer, msg_size, max_msgs); - return 0; + mq->msgq_buffer = k_malloc(msg_size * max_msgs); + k_msgq_init(&mq->msgq, mq->msgq_buffer, msg_size, max_msgs); + return 0; } int core_mq_send(core_mq_t *mq, const void *data, size_t msg_len) { - int ret = k_msgq_put(&mq->msgq, data, MQ_DEFAULT_TIMEOUT); + int ret = k_msgq_put(&mq->msgq, data, MQ_DEFAULT_TIMEOUT); - if (ret != 0) { - LOG_HEXDUMP_DBG(data, msg_len, "message"); - } - return ret; + if (ret != 0) { + LOG_HEXDUMP_DBG(data, msg_len, "message"); + } + return ret; } int core_mq_recv(core_mq_t *mq, void *data) { - return k_msgq_get(&mq->msgq, data, K_FOREVER); + return k_msgq_get(&mq->msgq, data, K_FOREVER); } diff --git a/src/shared/platform/zephyr/core_mutex.c b/src/shared/platform/zephyr/core_mutex.c index 6657891b..bd8f8034 100644 --- a/src/shared/platform/zephyr/core_mutex.c +++ b/src/shared/platform/zephyr/core_mutex.c @@ -8,25 +8,21 @@ #include "ocre_core_external.h" #include -int core_mutex_init(core_mutex_t *mutex) -{ - if (!mutex) - return -1; - k_mutex_init(&mutex->native_mutex); - return 0; +int core_mutex_init(core_mutex_t *mutex) { + if (!mutex) return -1; + k_mutex_init(&mutex->native_mutex); + return 0; } -int core_mutex_destroy(core_mutex_t *mutex) -{ - return 0; +int core_mutex_destroy(core_mutex_t *mutex) { + return 0; } -int core_mutex_lock(core_mutex_t *mutex) -{ - return k_mutex_lock(&mutex->native_mutex, K_FOREVER); +int core_mutex_lock(core_mutex_t *mutex) { + return k_mutex_lock(&mutex->native_mutex, K_FOREVER); } -int core_mutex_unlock(core_mutex_t *mutex) -{ - return k_mutex_unlock(&mutex->native_mutex); +int core_mutex_unlock(core_mutex_t *mutex) { + return k_mutex_unlock(&mutex->native_mutex); } + diff --git a/src/shared/platform/zephyr/core_thread.c b/src/shared/platform/zephyr/core_thread.c index 1c81191a..7bbd6fdd 100644 --- a/src/shared/platform/zephyr/core_thread.c +++ b/src/shared/platform/zephyr/core_thread.c @@ -9,32 +9,27 @@ #include #include -static void thread_entry(void *arg1, void *arg2, void *arg3) -{ - core_thread_func_t func = (core_thread_func_t)arg2; - void *user_arg = arg3; - func(user_arg); + +static void thread_entry(void *arg1, void *arg2, void *arg3) { + core_thread_func_t func = (core_thread_func_t)arg2; + void *user_arg = arg3; + func(user_arg); } -int core_thread_create(core_thread_t *thread, core_thread_func_t func, void *arg, const char *name, size_t stack_size, - int priority) -{ - if (!thread || !func) - return -1; - thread->stack = k_thread_stack_alloc(stack_size, 0); - if (!thread->stack) - return -1; - thread->tid = k_thread_create(&thread->thread, thread->stack, stack_size, thread_entry, NULL, (void *)func, arg, - priority, 0, K_NO_WAIT); - if (name) - k_thread_name_set(thread->tid, name); - return thread->tid ? 0 : -1; +int core_thread_create(core_thread_t *thread, core_thread_func_t func, void *arg, const char *name, size_t stack_size, int priority) { + if (!thread || !func) return -1; + thread->stack = k_thread_stack_alloc(stack_size, 0); + if (!thread->stack) return -1; + thread->tid = k_thread_create(&thread->thread, thread->stack, stack_size, + thread_entry, NULL, (void *)func, arg, + priority, 0, K_NO_WAIT); + if (name) + k_thread_name_set(thread->tid, name); + return thread->tid ? 0 : -1; } -void core_thread_destroy(core_thread_t *thread) -{ - if (!thread) - return; - k_thread_abort(thread->tid); - k_thread_stack_free(thread->stack); +void core_thread_destroy(core_thread_t *thread) { + if (!thread) return; + k_thread_abort(thread->tid); + k_thread_stack_free(thread->stack); } diff --git a/src/shared/platform/zephyr/core_timer.c b/src/shared/platform/zephyr/core_timer.c index 32d0520e..10da2d32 100644 --- a/src/shared/platform/zephyr/core_timer.c +++ b/src/shared/platform/zephyr/core_timer.c @@ -8,36 +8,30 @@ #include "ocre_core_external.h" #include -static void zephyr_timer_cb(struct k_timer *ktimer) -{ - core_timer_t *otimer = CONTAINER_OF(ktimer, core_timer_t, timer); - if (otimer->cb) { - otimer->cb(otimer->user_data); - } + +static void zephyr_timer_cb(struct k_timer *ktimer) { + core_timer_t *otimer = CONTAINER_OF(ktimer, core_timer_t, timer); + if (otimer->cb) { + otimer->cb(otimer->user_data); + } } -int core_timer_init(core_timer_t *timer, core_timer_callback_t cb, void *user_data) -{ - if (!timer) - return -1; - timer->cb = cb; - timer->user_data = user_data; - k_timer_init(&timer->timer, zephyr_timer_cb, NULL); - return 0; +int core_timer_init(core_timer_t *timer, core_timer_callback_t cb, void *user_data) { + if (!timer) return -1; + timer->cb = cb; + timer->user_data = user_data; + k_timer_init(&timer->timer, zephyr_timer_cb, NULL); + return 0; } -int core_timer_start(core_timer_t *timer, int timeout_ms, int period_ms) -{ - if (!timer) - return -1; - k_timer_start(&timer->timer, K_MSEC(timeout_ms), K_MSEC(period_ms)); - return 0; +int core_timer_start(core_timer_t *timer, int timeout_ms, int period_ms) { + if (!timer) return -1; + k_timer_start(&timer->timer, K_MSEC(timeout_ms), K_MSEC(period_ms)); + return 0; } -int core_timer_stop(core_timer_t *timer) -{ - if (!timer) - return -1; - k_timer_stop(&timer->timer); - return 0; +int core_timer_stop(core_timer_t *timer) { + if (!timer) return -1; + k_timer_stop(&timer->timer); + return 0; } From 933d2b2cc009948ff2bee1e6a1af51a996ba8eb9 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 7 Jan 2026 11:15:19 +0100 Subject: [PATCH 007/234] Revert "Enable AoT and fix ISA guess (#105)" This reverts commit 749461113e906f2a7d845cb4ce22a6730117f888. This commit is kept in the legacy branch. Signed-off-by: Marco Casaroli --- boards/b_u585i_iot02a.conf | 3 +- src/shared/platform/posix/ocre_internal.cmake | 2 +- .../platform/zephyr/ocre_internal.cmake | 31 +++++++------------ 3 files changed, 13 insertions(+), 23 deletions(-) diff --git a/boards/b_u585i_iot02a.conf b/boards/b_u585i_iot02a.conf index c273b586..90d47674 100644 --- a/boards/b_u585i_iot02a.conf +++ b/boards/b_u585i_iot02a.conf @@ -1,6 +1,5 @@ # Memory configuration and sizes -CONFIG_ARM_MPU=n -CONFIG_FPU=y +CONFIG_ARM_MPU=y CONFIG_MAIN_STACK_SIZE=8192 CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=-1 diff --git a/src/shared/platform/posix/ocre_internal.cmake b/src/shared/platform/posix/ocre_internal.cmake index f37a8480..675dbb3e 100644 --- a/src/shared/platform/posix/ocre_internal.cmake +++ b/src/shared/platform/posix/ocre_internal.cmake @@ -36,7 +36,7 @@ endif () set (WAMR_BUILD_PLATFORM "linux") set (WAMR_BUILD_INTERP 1) set (WAMR_BUILD_FAST_INTERP 0) -set (WAMR_BUILD_AOT 1) +set (WAMR_BUILD_AOT 0) set (WAMR_BUILD_JIT 0) set (WAMR_BUILD_LIBC_BUILTIN 0) set (WAMR_BUILD_LIBC_WASI 1) diff --git a/src/shared/platform/zephyr/ocre_internal.cmake b/src/shared/platform/zephyr/ocre_internal.cmake index cdf9c368..cccf6375 100644 --- a/src/shared/platform/zephyr/ocre_internal.cmake +++ b/src/shared/platform/zephyr/ocre_internal.cmake @@ -8,32 +8,23 @@ zephyr_compile_options(-DVERSION_BUILD_MACHINE="${BUILD_MACHINE}") message("BUILD_INFO: ${BUILD_INFO}") zephyr_compile_options(-DVERSION_BUILD_INFO="${BUILD_INFO}") -if (CONFIG_CPU_CORTEX_M33 OR CONFIG_CPU_CORTEX_M35P OR CONFIG_CPU_CORTEX_M55 OR CONFIG_CPU_CORTEX_M85) - # ARMv8-M Mainline (Cortex-M33, M35P, M55, M85) - set (TARGET_ISA THUMBV8M) -elseif (CONFIG_CPU_CORTEX_M23) - # ARMv8-M Baseline (Cortex-M23) - set (TARGET_ISA THUMBV8M) -elseif (CONFIG_CPU_CORTEX_M7 OR CONFIG_CPU_CORTEX_M4) - # ARMv7E-M (Cortex-M4, M7) - set (TARGET_ISA THUMBV7EM) -elseif (DEFINED CONFIG_ISA_THUMB2) - # Generic Thumb-2 - set (TARGET_ISA THUMB) +# Determine the ISA of the target and set appropriately +if (DEFINED CONFIG_ISA_THUMB2) + set(TARGET_ISA THUMB) elseif (DEFINED CONFIG_ISA_ARM) - set (TARGET_ISA ARM) + set(TARGET_ISA ARM) elseif (DEFINED CONFIG_X86) - set (TARGET_ISA X86_32) + set(TARGET_ISA X86_32) elseif (DEFINED CONFIG_XTENSA) - set (TARGET_ISA XTENSA) + set(TARGET_ISA XTENSA) elseif (DEFINED CONFIG_RISCV) - set (TARGET_ISA RISCV32) + set(TARGET_ISA RISCV32) elseif (DEFINED CONFIG_ARCH_POSIX) - set (TARGET_ISA X86_32) + set(TARGET_ISA X86_32) else () - message (FATAL_ERROR "Unsupported ISA: ${CONFIG_ARCH}") + message(FATAL_ERROR "Unsupported ISA: ${CONFIG_ARCH}") endif () -message(STATUS "TARGET ISA: ${TARGET_ISA}") +message("TARGET ISA: ${TARGET_ISA}") add_compile_options(-O0 -Wno-unknown-attributes) @@ -42,7 +33,7 @@ set(WAMR_BUILD_PLATFORM "zephyr") set(WAMR_BUILD_TARGET ${TARGET_ISA}) set(WAMR_BUILD_INTERP 1) set(WAMR_BUILD_FAST_INTERP 0) -set(WAMR_BUILD_AOT 1) +set(WAMR_BUILD_AOT 0) set(WAMR_BUILD_JIT 0) set(WAMR_BUILD_LIBC_BUILTIN 0) set(WAMR_BUILD_LIBC_WASI 1) From 6d88562d8ff6e1f3f7e5528226ee2adc73e731ba Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 7 Jan 2026 11:15:23 +0100 Subject: [PATCH 008/234] Revert "Add exception handling (#104)" This reverts commit cafad42cbce2a107dc4701b5a77b94db0b13f5a0. This commit is kept in the legacy branch. Signed-off-by: Marco Casaroli --- .../container_supervisor/cs_sm_impl.c | 26 +++---------------- src/ocre/ocre_gpio/ocre_gpio.c | 2 +- wasm-micro-runtime | 2 +- 3 files changed, 5 insertions(+), 25 deletions(-) diff --git a/src/ocre/components/container_supervisor/cs_sm_impl.c b/src/ocre/components/container_supervisor/cs_sm_impl.c index 229cb33a..e7bc3312 100644 --- a/src/ocre/components/container_supervisor/cs_sm_impl.c +++ b/src/ocre/components/container_supervisor/cs_sm_impl.c @@ -131,23 +131,8 @@ static void container_thread_entry(void *args) { // Set TLS for the container's WASM module current_module_tls = &module_inst; #endif - - // Run the WASM main function with exception handling - bool success = false; - const char *exception = NULL; - - // Clear any previous exceptions - wasm_runtime_clear_exception(module_inst); - - // Execute main function - success = wasm_application_execute_main(module_inst, 0, NULL); - - // Check for exceptions - exception = wasm_runtime_get_exception(module_inst); - if (exception) { - LOG_ERR("Container %d exception: %s", container->container_ID, exception); - success = false; - } + // Run the WASM main function + bool success = wasm_application_execute_main(module_inst, 0, NULL); // Update container status if (container->container_runtime_status != CONTAINER_STATUS_STOPPED) container->container_runtime_status = success ? CONTAINER_STATUS_STOPPED : CONTAINER_STATUS_ERROR; @@ -176,12 +161,7 @@ static void container_thread_entry(void *args) { } core_mutex_unlock(&container->lock); - if (success) { - LOG_INF("Container %d completed successfully", container->container_ID); - } else { - LOG_ERR("Container %d failed: %s", container->container_ID, - exception ? exception : "unknown error"); - } + LOG_INF("Container thread %d exited cleanly", container->container_ID); // Clean up WASM runtime thread environment wasm_runtime_destroy_thread_env(); diff --git a/src/ocre/ocre_gpio/ocre_gpio.c b/src/ocre/ocre_gpio/ocre_gpio.c index 7a32de9c..e99351e2 100644 --- a/src/ocre/ocre_gpio/ocre_gpio.c +++ b/src/ocre/ocre_gpio/ocre_gpio.c @@ -267,7 +267,7 @@ int ocre_gpio_unregister_callback(int pin) { void ocre_gpio_cleanup_container(wasm_module_inst_t module_inst) { if (!gpio_system_initialized || !module_inst) { - LOG_DBG("GPIO system not initialized or invalid module %p", (void *)module_inst); + LOG_ERR("GPIO system not initialized or invalid module %p", (void *)module_inst); return; } for (int i = 0; i < CONFIG_OCRE_GPIO_MAX_PINS; i++) { diff --git a/wasm-micro-runtime b/wasm-micro-runtime index 60253bed..c9cf93fb 160000 --- a/wasm-micro-runtime +++ b/wasm-micro-runtime @@ -1 +1 @@ -Subproject commit 60253bedbbbc16ff586381f3cd142f639ce23d94 +Subproject commit c9cf93fb10fe31e229658937a9afa2fbb41fb009 From d2731a2b2f35bab19e586f8f3f6903e5dd0a5fcc Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 7 Jan 2026 11:15:26 +0100 Subject: [PATCH 009/234] Revert "Add RT1064 GPIO config (#103)" This reverts commit e9d8d040b5c5acb72cda5047bd9308b7be6e960a. This commit is kept in the legacy branch. Signed-off-by: Marco Casaroli --- src/ocre/ocre_gpio/ocre_gpio.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/ocre/ocre_gpio/ocre_gpio.c b/src/ocre/ocre_gpio/ocre_gpio.c index e99351e2..1c4b71bf 100644 --- a/src/ocre/ocre_gpio/ocre_gpio.c +++ b/src/ocre/ocre_gpio/ocre_gpio.c @@ -104,18 +104,6 @@ int ocre_gpio_init(void) { #elif defined(CONFIG_BOARD_W5500_EVB_PICO2) INIT_GPIO_PORT_NAMED(0, DT_NODELABEL(gpio0), "GPIO0"); -#elif defined(CONFIG_BOARD_MIMXRT1064_EVK) - // No gpio0 for some reason? Will be annoying for some APIs - INIT_GPIO_PORT_NAMED(0, DT_NODELABEL(gpio1), "GPIO1"); - INIT_GPIO_PORT_NAMED(1, DT_NODELABEL(gpio2), "GPIO2"); - INIT_GPIO_PORT_NAMED(2, DT_NODELABEL(gpio3), "GPIO3"); - INIT_GPIO_PORT_NAMED(3, DT_NODELABEL(gpio4), "GPIO4"); - INIT_GPIO_PORT_NAMED(4, DT_NODELABEL(gpio5), "GPIO5"); - INIT_GPIO_PORT_NAMED(5, DT_NODELABEL(gpio6), "GPIO6"); - INIT_GPIO_PORT_NAMED(6, DT_NODELABEL(gpio7), "GPIO7"); - INIT_GPIO_PORT_NAMED(7, DT_NODELABEL(gpio8), "GPIO8"); - INIT_GPIO_PORT_NAMED(8, DT_NODELABEL(gpio9), "GPIO9"); - #else // Generic fallback #if DT_NODE_EXISTS(DT_NODELABEL(gpio0)) From b9a32d7c15358409782268f4addbc643006a13f0 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 7 Jan 2026 11:15:30 +0100 Subject: [PATCH 010/234] Revert "Ocre containers: Adding support for NRF5340-DK board (#93)" This reverts commit 4778e5c5f79591078b7cb18cb6dd72c41a5f66ed. This commit is kept in the legacy branch. Signed-off-by: Marco Casaroli --- boards/nrf5340dk_nrf5340_cpuapp.conf | 79 ------------------------- boards/nrf5340dk_nrf5340_cpuapp.overlay | 34 ----------- build.sh | 5 -- src/ocre/ocre_gpio/ocre_gpio.c | 8 +-- west.yml | 5 +- 5 files changed, 6 insertions(+), 125 deletions(-) delete mode 100644 boards/nrf5340dk_nrf5340_cpuapp.conf delete mode 100644 boards/nrf5340dk_nrf5340_cpuapp.overlay diff --git a/boards/nrf5340dk_nrf5340_cpuapp.conf b/boards/nrf5340dk_nrf5340_cpuapp.conf deleted file mode 100644 index 501754d7..00000000 --- a/boards/nrf5340dk_nrf5340_cpuapp.conf +++ /dev/null @@ -1,79 +0,0 @@ -CONFIG_ARM_MPU=y -CONFIG_MAIN_STACK_SIZE=4096 -CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 -CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=-1 -CONFIG_HEAP_MEM_POOL_SIZE=32768 - -# Container defaults - Reduced for nRF5340's limited RAM -CONFIG_MAX_CONTAINERS=2 -CONFIG_OCRE_WAMR_HEAP_BUFFER_SIZE=180000 -CONFIG_OCRE_CONTAINER_DEFAULT_HEAP_SIZE=4096 -CONFIG_OCRE_CONTAINER_DEFAULT_STACK_SIZE=4096 - -# DISABLE OCRE SHELL (this is what's causing the shell_fprintf errors!) -CONFIG_OCRE_SHELL=n - -# Disable the main Zephyr shell AND all shell subsystems -CONFIG_NET_SHELL=n -CONFIG_FILE_SYSTEM_SHELL=n -CONFIG_SENSOR_SHELL=n - -# Override shell-related configs from prj.conf since shell is disabled - -# Random number generator (REQUIRED by networking and RNG sensor) -CONFIG_ENTROPY_GENERATOR=y -CONFIG_TEST_RANDOM_GENERATOR=y - -# Reduce networking stack sizes to save RAM -CONFIG_NET_TX_STACK_SIZE=1024 -CONFIG_NET_RX_STACK_SIZE=2048 -CONFIG_NET_BUF_TX_COUNT=8 -CONFIG_NET_BUF_RX_COUNT=16 -CONFIG_NET_MGMT_EVENT_STACK_SIZE=1024 -CONFIG_NET_PKT_RX_COUNT=8 -CONFIG_NET_PKT_TX_COUNT=8 -CONFIG_NET_BUF_DATA_SIZE=128 - -# Bus interfaces -CONFIG_GPIO=y - -# Ocre Sensors support -CONFIG_SENSOR=y -CONFIG_OCRE_SENSORS=y -CONFIG_RNG_SENSOR=y - -# Ocre GPIO Support (minimal) -CONFIG_OCRE_GPIO=y -CONFIG_OCRE_GPIO_MAX_PORTS=4 -CONFIG_OCRE_GPIO_PINS_PER_PORT=8 -CONFIG_OCRE_GPIO_MAX_PINS=32 - -# Disable container messaging to save RAM -CONFIG_OCRE_CONTAINER_MESSAGING=y - -# Enable container filesystem for WASI stdio -CONFIG_OCRE_CONTAINER_FILESYSTEM=y - -# CONFIG_BOOTLOADER_MCUBOOT=n -# # CONFIG_IMG_MANAGER=n -# CONFIG_MCUBOOT_IMG_MANAGER=n -# CONFIG_STREAM_FLASH=n -# CONFIG_IMG_ERASE_PROGRESSIVELY=n - -# Flash settings -CONFIG_FLASH=y -CONFIG_FLASH_MAP=y -CONFIG_FLASH_PAGE_LAYOUT=y - -# Serial/UART -CONFIG_SERIAL=y -CONFIG_UART_CONSOLE=y -CONFIG_CONSOLE=y - -# Reduce other buffers -CONFIG_ZVFS_OPEN_MAX=8 -CONFIG_ZVFS_EVENTFD_MAX=5 - -CONFIG_LOG_TRACE_SHORT_TIMESTAMP=n - -CONFIG_SHELL_PROMPT_UART="" diff --git a/boards/nrf5340dk_nrf5340_cpuapp.overlay b/boards/nrf5340dk_nrf5340_cpuapp.overlay deleted file mode 100644 index 7d625007..00000000 --- a/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ /dev/null @@ -1,34 +0,0 @@ -/ { - aliases { - rng0 = &rng_device; - led0 = &led0; - }; - - rng_device: rng_0 { - compatible = "custom,rng-sensor"; - label = "RNG Sensor"; - status = "okay"; - }; - - devices { - compatible = "custom,devices"; - status = "okay"; - device_list = <&rng_device>; - }; -}; - -/* Enable one LED for blinky */ -&led0 { - status = "okay"; -}; - -&flash0 { - partitions { - /delete-node/ partition@f8000; - - user_data_partition: partition@e0000 { - label = "user_data"; - reg = <0x000e0000 DT_SIZE_K(128)>; - }; - }; -}; diff --git a/build.sh b/build.sh index 8432e0c4..ac1da7b8 100755 --- a/build.sh +++ b/build.sh @@ -91,11 +91,6 @@ if [[ "$TARGET" == "z" ]]; then -DDTC_OVERLAY_FILE=boards/${ZEPHYR_BOARD}.overlay\;boards/enc28j60.overlay" echo "Building for b_u585i_iot02a with ENC28J60 support" ;; - nrf5340) - ZEPHYR_BOARD="nrf5340dk/nrf5340/cpuapp" - CONF_EXTRA="" - echo "Building for nrf5340dk board: App CPU" - ;; *) ZEPHYR_BOARD="$BOARD_ARG" CONF_EXTRA="" diff --git a/src/ocre/ocre_gpio/ocre_gpio.c b/src/ocre/ocre_gpio/ocre_gpio.c index 1c4b71bf..63004048 100644 --- a/src/ocre/ocre_gpio/ocre_gpio.c +++ b/src/ocre/ocre_gpio/ocre_gpio.c @@ -384,7 +384,7 @@ static void gpio_callback_handler(const struct device *port, struct gpio_callbac } //======================================================================================================================================================================================================================================================================================================== -// By Name +// By Name //======================================================================================================================================================================================================================================================================================================== static int find_port_index(const struct device *port) { if (!port) { @@ -662,12 +662,12 @@ int ocre_gpio_wasm_register_callback_by_name(wasm_exec_env_t exec_env, const cha int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; LOG_INF("Registering callback by name: %s, global_pin=%d", name, global_pin); - + if (global_pin >= CONFIG_OCRE_GPIO_MAX_PINS) { LOG_ERR("Global pin %d exceeds max %d", global_pin, CONFIG_OCRE_GPIO_MAX_PINS); return -EINVAL; } - + return ocre_gpio_register_callback(global_pin); } @@ -686,6 +686,6 @@ int ocre_gpio_wasm_unregister_callback_by_name(wasm_exec_env_t exec_env, const c int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; LOG_INF("Unregistering callback by name: %s, global_pin=%d", name, global_pin); - + return ocre_gpio_unregister_callback(global_pin); } diff --git a/west.yml b/west.yml index 3e8d71a1..cee4e7bb 100644 --- a/west.yml +++ b/west.yml @@ -14,7 +14,6 @@ manifest: - hal_st - mbedtls - cmsis_6 - - hal_nordic - + self: - path: application + path: application From c1c76adfde044e1c58a39aeea89d9378e5b78c80 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 7 Jan 2026 11:15:33 +0100 Subject: [PATCH 011/234] Revert "Add shared memory and DNS resolution support (#99)" This reverts commit f555f1b0e7c2c3fd6910b79988974a495ca35a0d. This commit is kept in the legacy branch. Signed-off-by: Marco Casaroli --- Kconfig | 50 +------------ .../container_supervisor/cs_sm_impl.c | 70 +------------------ src/shared/platform/posix/ocre_internal.cmake | 1 - .../platform/zephyr/ocre_internal.cmake | 1 - wasm-micro-runtime | 2 +- 5 files changed, 3 insertions(+), 121 deletions(-) diff --git a/Kconfig b/Kconfig index b6c78320..bf2d4a01 100644 --- a/Kconfig +++ b/Kconfig @@ -224,53 +224,5 @@ config OCRE_NETWORKING default n help Enable networking support for containers. - -config OCRE_SHARED_HEAP - bool "Enable container shared heap support" - default n - help - Enable shared heap support for containers. - -config OCRE_SHARED_HEAP_BUF_SIZE - int "Shared heap buffer size in bytes" - default 65536 - depends on OCRE_SHARED_HEAP - help - Size of the pre-allocated buffer for the shared heap. - This memory is shared between WebAssembly modules. - -choice OCRE_SHARED_HEAP_MODE - prompt "Shared heap mode" - depends on OCRE_SHARED_HEAP - default OCRE_SHARED_HEAP_BUF_VIRTUAL - help - Select the shared heap memory mode: - - Physical: Map physical hardware registers (e.g., GPIO) to WASM address space - - Virtual: Allocate shared heap from regular RAM - -config OCRE_SHARED_HEAP_BUF_PHYSICAL - bool "Physical (hardware register mapping)" - help - Enable physical memory mapping for hardware access. - Maps physical hardware registers (like GPIO at 0x42020000) to WASM address space. - Use this when containers need direct access to hardware peripherals. - -config OCRE_SHARED_HEAP_BUF_VIRTUAL - bool "Virtual (RAM allocation)" - help - Enable virtual shared heap allocated from regular RAM. - Use this for normal inter-module communication without - direct hardware access. - -endchoice - -config OCRE_SHARED_HEAP_BUF_ADDRESS - hex "Shared heap buffer address" - default 0x00 - depends on OCRE_SHARED_HEAP - help - Shared heap buffer address. - - For physical mode: Physical address of hardware registers - - For virtual mode: Leave as 0x00 to auto-allocate from RAM - + endmenu diff --git a/src/ocre/components/container_supervisor/cs_sm_impl.c b/src/ocre/components/container_supervisor/cs_sm_impl.c index e7bc3312..04ba07ae 100644 --- a/src/ocre/components/container_supervisor/cs_sm_impl.c +++ b/src/ocre/components/container_supervisor/cs_sm_impl.c @@ -73,14 +73,6 @@ static size_t ocre_get_available_memory(void) { } #endif -#ifdef CONFIG_OCRE_SHARED_HEAP -// Shared heap for memory-mapped access -wasm_shared_heap_t _shared_heap = NULL; -#ifdef CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL -uint8 preallocated_buf[CONFIG_OCRE_SHARED_HEAP_BUF_SIZE]; -#endif -#endif - static bool validate_container_memory(ocre_container_t *container) { #ifdef CONFIG_OCRE_MEMORY_CHECK_ENABLED size_t requested_heap = container->ocre_container_data.heap_size; @@ -274,30 +266,6 @@ ocre_container_runtime_status_t CS_runtime_init(ocre_cs_ctx *ctx, ocre_container #ifdef CONFIG_OCRE_CONTAINER_MESSAGING ocre_messaging_init(); #endif -#ifdef CONFIG_OCRE_SHARED_HEAP - SharedHeapInitArgs heap_init_args; - memset(&heap_init_args, 0, sizeof(heap_init_args)); - -#ifdef CONFIG_OCRE_SHARED_HEAP_BUF_PHYSICAL - // Physical mode - map hardware register address - heap_init_args.pre_allocated_addr = (void *)CONFIG_OCRE_SHARED_HEAP_BUF_ADDRESS; - LOG_INF("Creating physical memory mapping at 0x%08X (hardware registers)", - CONFIG_OCRE_SHARED_HEAP_BUF_ADDRESS); -#elif CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL - // Virtual mode - allocate from RAM - heap_init_args.pre_allocated_addr = preallocated_buf; - LOG_INF("Creating virtual shared heap in RAM, size=%d bytes", - CONFIG_OCRE_SHARED_HEAP_BUF_SIZE); -#endif - heap_init_args.size = CONFIG_OCRE_SHARED_HEAP_BUF_SIZE; - _shared_heap = wasm_runtime_create_shared_heap(&heap_init_args); - - if (!_shared_heap) { - LOG_ERR("Create preallocated shared heap failed"); - return RUNTIME_STATUS_ERROR; - } -#endif - storage_heap_init(); return RUNTIME_STATUS_INITIALIZED; } @@ -384,15 +352,6 @@ ocre_container_status_t CS_run_container(ocre_container_t *container) { "0.0.0.0/0", }; wasm_runtime_set_wasi_addr_pool(curr_container_arguments->module, addr_pool, ADDRESS_POOL_SIZE); - /** - * Configure which domain names a WebAssembly module is allowed to resolve via DNS lookups - * ns_lookup_pool: An array of domain name patterns (e.g., "example.com", "*.example.com", or "*" for any domain) - */ - - const char *ns_lookup_pool[] = { - "*" - }; - wasm_runtime_set_wasi_ns_lookup_pool(curr_container_arguments->module, ns_lookup_pool, sizeof(ns_lookup_pool) / sizeof(ns_lookup_pool[0])); #endif #ifdef CONFIG_OCRE_CONTAINER_FILESYSTEM @@ -427,36 +386,9 @@ ocre_container_status_t CS_run_container(ocre_container_t *container) { #if defined(CONFIG_OCRE_TIMER) || defined(CONFIG_OCRE_GPIO) || defined(CONFIG_OCRE_SENSORS) || \ defined(CONFIG_OCRE_CONTAINER_MESSAGING) ocre_register_module(curr_container_arguments->module_inst); -#endif -#ifdef CONFIG_OCRE_SHARED_HEAP - LOG_INF("Attaching shared heap to container %d", curr_container_ID); - /* attach module instance to the shared heap */ - if (!wasm_runtime_attach_shared_heap(curr_container_arguments->module_inst, _shared_heap)) { - LOG_ERR("Attach shared heap failed."); - return CONTAINER_STATUS_ERROR; - } - -#ifdef CONFIG_OCRE_SHARED_HEAP_BUF_PHYSICAL - // For physical mode, get the base address from the shared heap itself - // The WASM address space already knows about the physical mapping - uint32 shared_heap_base_addr = wasm_runtime_addr_native_to_app( - curr_container_arguments->module_inst, - (void*)CONFIG_OCRE_SHARED_HEAP_BUF_ADDRESS); - LOG_INF("Physical shared heap base address in app: 0x%x", shared_heap_base_addr); -#elif CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL - // For virtual mode, convert the allocated buffer address - uint32 shared_heap_base_addr = wasm_runtime_addr_native_to_app( - curr_container_arguments->module_inst, - preallocated_buf); - LOG_INF("Virtual shared heap base address in app: 0x%x", shared_heap_base_addr); -#endif - - if (shared_heap_base_addr == 0) { - LOG_ERR("Failed to get shared heap WASM address!"); - return CONTAINER_STATUS_ERROR; - } #endif } + core_mutex_lock(&container_mutex); int thread_idx = get_available_thread(); if (thread_idx == -1) { diff --git a/src/shared/platform/posix/ocre_internal.cmake b/src/shared/platform/posix/ocre_internal.cmake index 675dbb3e..03ec062b 100644 --- a/src/shared/platform/posix/ocre_internal.cmake +++ b/src/shared/platform/posix/ocre_internal.cmake @@ -43,7 +43,6 @@ set (WAMR_BUILD_LIBC_WASI 1) set (WAMR_BUILD_LIB_PTHREAD 1) set (WAMR_BUILD_REF_TYPES 1) set (WASM_ENABLE_LOG 1) -set (WAMR_BUILD_SHARED_HEAP 1) if (NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_POOL) set (WAMR_BUILD_GLOBAL_HEAP_POOL 1) diff --git a/src/shared/platform/zephyr/ocre_internal.cmake b/src/shared/platform/zephyr/ocre_internal.cmake index cccf6375..38fbcd16 100644 --- a/src/shared/platform/zephyr/ocre_internal.cmake +++ b/src/shared/platform/zephyr/ocre_internal.cmake @@ -40,7 +40,6 @@ set(WAMR_BUILD_LIBC_WASI 1) set(WAMR_BUILD_LIB_PTHREAD 1) set(WAMR_BUILD_REF_TYPES 1) set(WASM_ENABLE_LOG 1) -set (WAMR_BUILD_SHARED_HEAP 1) if(NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_POOL) set(WAMR_BUILD_GLOBAL_HEAP_POOL 1) diff --git a/wasm-micro-runtime b/wasm-micro-runtime index c9cf93fb..ce279ef9 160000 --- a/wasm-micro-runtime +++ b/wasm-micro-runtime @@ -1 +1 @@ -Subproject commit c9cf93fb10fe31e229658937a9afa2fbb41fb009 +Subproject commit ce279ef9c45158c6fd4c6816f87581b1175c3818 From 2aa1af01448be3bbdcdedeb56f23d542b7c2e2b9 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 7 Jan 2026 11:15:37 +0100 Subject: [PATCH 012/234] Revert "const sample container (#101)" This reverts commit 6c985885b98b6dfbff479fbd6a6b376703d6f766. This commit is kept in the legacy branch. Signed-off-by: Marco Casaroli --- CMakeLists.txt | 2 +- src/ocre/ocre_input_file.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ce15320..38367542 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,7 +65,7 @@ if(NOT "${OCRE_INPUT_FILE}" STREQUAL "") add_custom_command( OUTPUT ${CMAKE_CURRENT_LIST_DIR}/src/ocre/ocre_input_file.g - COMMAND xxd -n wasm_binary -i ${OCRE_INPUT_FILE} | sed 's/^unsigned/static const unsigned/' > ${OCRE_ROOT_DIR}/src/ocre/ocre_input_file.g + COMMAND xxd -i ${OCRE_INPUT_FILE} | sed 's/unsigned char .*\\[/static const unsigned char wasm_binary[/' | sed 's/unsigned int .*_len/static const unsigned int wasm_binary_len/' > ${CMAKE_CURRENT_LIST_DIR}/src/ocre/ocre_input_file.g DEPENDS ${OCRE_INPUT_FILE} COMMENT "Generating C header from ${OCRE_INPUT_FILE}" ) diff --git a/src/ocre/ocre_input_file.h b/src/ocre/ocre_input_file.h index fea12761..74a39052 100644 --- a/src/ocre/ocre_input_file.h +++ b/src/ocre/ocre_input_file.h @@ -8,7 +8,7 @@ #ifndef OCRE_INPUT_FILE_H #define OCRE_INPUT_FILE_H // Sample WASM binary data -static const unsigned char wasm_binary[] = { +static unsigned char wasm_binary[] = { 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x35, 0x09, 0x60, 0x03, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x03, 0x7f, 0x7e, 0x7f, 0x01, 0x7e, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, @@ -332,6 +332,6 @@ static const unsigned char wasm_binary[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00 }; -static const unsigned int wasm_binary_len = 3850; +static unsigned int wasm_binary_len = 3850; #endif // OCRE_INPUT_FILE_H From 79cf1cf8bf751e08fd6cc7153f243682b9691c9c Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 7 Jan 2026 11:15:40 +0100 Subject: [PATCH 013/234] Revert "fix(sample_container): truncate file (#100)" This reverts commit 734ed5ce3973e04e36bc9bf64b7f40519ec31e72. This commit is kept in the legacy branch. Signed-off-by: Marco Casaroli --- src/samples-mini/zephyr/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/samples-mini/zephyr/main.c b/src/samples-mini/zephyr/main.c index 034baed0..049bb203 100644 --- a/src/samples-mini/zephyr/main.c +++ b/src/samples-mini/zephyr/main.c @@ -87,7 +87,7 @@ void create_sample_container(char *file_name) { int res; fs_file_t_init(&f); - res = fs_open(&f, file_path, FS_O_CREATE | FS_O_TRUNC | FS_O_RDWR); + res = fs_open(&f, file_path, FS_O_CREATE | FS_O_RDWR); fs_write(&f, &wasm_binary, wasm_binary_len); fs_close(&f); From 5f96834c96821fdb92244f38537236f463b13b73 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 17 Nov 2025 15:37:03 +0100 Subject: [PATCH 014/234] feat(ocre): introduce user heap the user_malloc and user_free functions will be used on platforms with support for external PSRAM. This way we can differentiate allocations in the internal or external RAM. Signed-off-by: Marco Casaroli --- src/shared/platform/ocre_core_external.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/shared/platform/ocre_core_external.h b/src/shared/platform/ocre_core_external.h index 69375219..79efb20f 100644 --- a/src/shared/platform/ocre_core_external.h +++ b/src/shared/platform/ocre_core_external.h @@ -142,6 +142,30 @@ void *core_malloc(size_t size); */ void core_free(void *ptr); +/** + * @brief Allocate memory in application heap. + * + * @param size Number of bytes to allocate. + * @return Pointer to allocated memory, or NULL on failure. + */ +void *user_malloc(size_t size); + +/** + * @brief Free previously allocated memory in application heap. + * + * @param ptr Pointer to memory to free. + */ +void user_free(void *ptr); + +/** + * @brief Reallocate memory in application heap. + * + * @param ptr pointer to already allocated memory + * @param size Number of bytes to allocate. + * @return Pointer to reallocated memory, or NULL on failure. + */ +void *user_realloc(void *ptr, size_t size); + /** * @brief Yield the current thread's execution. */ From 9719d847a8f0b8799563d4927d5b13124726336f Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 17 Nov 2025 15:37:50 +0100 Subject: [PATCH 015/234] feat(zephyr): use shared multi heap for user heap These functions allocate memory on external PSRAM on boards that have CONFIG_SHARED_MULTI_HEAP enabled. Otherwise, they work just like core_malloc and core_free. Signed-off-by: Marco Casaroli --- src/shared/platform/zephyr/core_memory.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/shared/platform/zephyr/core_memory.c b/src/shared/platform/zephyr/core_memory.c index 3655ed4b..78a55c73 100644 --- a/src/shared/platform/zephyr/core_memory.c +++ b/src/shared/platform/zephyr/core_memory.c @@ -8,6 +8,7 @@ #include "ocre_core_external.h" #include +#include void *core_malloc(size_t size) { return k_malloc(size); @@ -16,3 +17,22 @@ void *core_malloc(size_t size) { void core_free(void *ptr) { k_free(ptr); } + +#ifdef CONFIG_SHARED_MULTI_HEAP +void *user_malloc(size_t size) { + return shared_multi_heap_aligned_alloc(SMH_REG_ATTR_EXTERNAL, 32, size); +} + +void user_free(void *ptr) { + shared_multi_heap_free(ptr); +} +#else +#warning CONFIG_SHARED_MULTI_HEAP is not defined. Using internal RAM +void *user_malloc(size_t size) { + return k_malloc(size); +} + +void user_free(void *ptr) { + k_free(ptr); +} +#endif From 85906d063e4622d440a5e5415d0560ab98fedf0c Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 17 Nov 2025 15:39:15 +0100 Subject: [PATCH 016/234] feat(posix): dummy user heap wrapper On systems with a single heap, these functions work exactly the same as malloc and free. Signed-off-by: Marco Casaroli --- src/shared/platform/posix/core_memory.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/shared/platform/posix/core_memory.c b/src/shared/platform/posix/core_memory.c index 0e13a8c0..04d0ae7d 100644 --- a/src/shared/platform/posix/core_memory.c +++ b/src/shared/platform/posix/core_memory.c @@ -16,3 +16,15 @@ void *core_malloc(size_t size) { void core_free(void *ptr) { free(ptr); } + +void *user_malloc(size_t size) { + return malloc(size); +} + +void user_free(void *ptr) { + free(ptr); +} + +void *user_realloc(void *ptr, size_t size) { + return realloc(ptr, size); +} From 2d840464d8c79b6cde470d88fce76b78c14d53bc Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 17 Nov 2025 15:40:35 +0100 Subject: [PATCH 017/234] feat(fs): load wasm module in user heap The user heap is user for large objects. Signed-off-by: Marco Casaroli --- src/shared/platform/posix/core_fs.c | 6 +++--- src/shared/platform/zephyr/core_fs.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/shared/platform/posix/core_fs.c b/src/shared/platform/posix/core_fs.c index 76c2fddd..fc559b14 100644 --- a/src/shared/platform/posix/core_fs.c +++ b/src/shared/platform/posix/core_fs.c @@ -73,11 +73,11 @@ int core_filestat(const char *path, size_t *size) { } int core_fileopen(const char *path, void **handle) { - int *fd = core_malloc(sizeof(int)); + int *fd = user_malloc(sizeof(int)); if (!fd) return -ENOMEM; *fd = open(path, O_RDONLY); if (*fd < 0) { - core_free(fd); + user_free(fd); return -errno; } *handle = fd; @@ -95,7 +95,7 @@ int core_fileread(void *handle, void *buffer, size_t size) { int core_fileclose(void *handle) { int fd = *(int *)handle; int ret = close(fd); - core_free(handle); + user_free(handle); return ret; } diff --git a/src/shared/platform/zephyr/core_fs.c b/src/shared/platform/zephyr/core_fs.c index ef08a6de..42f1d614 100644 --- a/src/shared/platform/zephyr/core_fs.c +++ b/src/shared/platform/zephyr/core_fs.c @@ -47,12 +47,12 @@ int core_filestat(const char *path, size_t *size) { } int core_fileopen(const char *path, void **handle) { - struct fs_file_t *file = core_malloc(sizeof(struct fs_file_t)); + struct fs_file_t *file = user_malloc(sizeof(struct fs_file_t)); if (!file) return -ENOMEM; fs_file_t_init(file); int ret = fs_open(file, path, FS_O_READ); if (ret < 0) { - core_free(file); + user_free(file); return ret; } *handle = file; @@ -67,7 +67,7 @@ int core_fileread(void *handle, void *buffer, size_t size) { int core_fileclose(void *handle) { struct fs_file_t *file = (struct fs_file_t *)handle; int ret = fs_close(file); - core_free(file); + user_free(file); return ret; } From 7d22e78247d40a52c6888fc2c76b7768d1a2f31f Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 17 Nov 2025 16:00:03 +0100 Subject: [PATCH 018/234] feat(zephyr): realloc stub Signed-off-by: Marco Casaroli --- src/shared/platform/zephyr/core_memory.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/shared/platform/zephyr/core_memory.c b/src/shared/platform/zephyr/core_memory.c index 78a55c73..d295b32c 100644 --- a/src/shared/platform/zephyr/core_memory.c +++ b/src/shared/platform/zephyr/core_memory.c @@ -26,6 +26,12 @@ void *user_malloc(size_t size) { void user_free(void *ptr) { shared_multi_heap_free(ptr); } + +void *user_realloc(void *ptr, size_t size) { + // TODO + return NULL; +} + #else #warning CONFIG_SHARED_MULTI_HEAP is not defined. Using internal RAM void *user_malloc(size_t size) { @@ -35,4 +41,9 @@ void *user_malloc(size_t size) { void user_free(void *ptr) { k_free(ptr); } + +void *user_realloc(void *ptr, size_t size) { + return k_realloc(ptr, size); +} + #endif From 7b96301d452e2d8280d0c7241396a8fbe2751bd1 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 17 Nov 2025 16:03:57 +0100 Subject: [PATCH 019/234] feat(wamr): use user heap Use the user heap for wamr and related container memory. Signed-off-by: Marco Casaroli --- .../container_supervisor/cs_sm_impl.c | 35 ++++++++----------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/src/ocre/components/container_supervisor/cs_sm_impl.c b/src/ocre/components/container_supervisor/cs_sm_impl.c index 04ba07ae..c4addb56 100644 --- a/src/ocre/components/container_supervisor/cs_sm_impl.c +++ b/src/ocre/components/container_supervisor/cs_sm_impl.c @@ -34,15 +34,6 @@ LOG_MODULE_DECLARE(ocre_cs_component, OCRE_LOG_LEVEL); #include "cs_sm.h" #include "cs_sm_impl.h" -#include "ocre_psram.h" - -// WAMR heap buffer - uses PSRAM when available -#if defined(CONFIG_MEMC) - PSRAM_SECTION_ATTR -#endif -static char wamr_heap_buf[CONFIG_OCRE_WAMR_HEAP_BUFFER_SIZE] = {0}; - - // Thread pool for container execution #define CONTAINER_THREAD_POOL_SIZE 4 static core_thread_t container_threads[CONTAINER_THREAD_POOL_SIZE]; @@ -189,7 +180,7 @@ static int load_binary_to_buffer_fs(ocre_runtime_arguments_t *container_argument } container_arguments->size = file_size; - container_arguments->buffer = storage_heap_alloc(file_size); + container_arguments->buffer = user_malloc(file_size); if (!container_arguments->buffer) { LOG_ERR("Failed to allocate memory for container binary from PSRAM."); return -ENOMEM; @@ -200,7 +191,7 @@ static int load_binary_to_buffer_fs(ocre_runtime_arguments_t *container_argument ret = core_fileopen(filepath, &file_handle); if (ret < 0) { LOG_ERR("Failed to open file %s: %d", filepath, ret); - storage_heap_free(container_arguments->buffer); + user_free(container_arguments->buffer); return ret; } @@ -208,14 +199,14 @@ static int load_binary_to_buffer_fs(ocre_runtime_arguments_t *container_argument if (ret < 0) { LOG_ERR("Failed to read file %s: %d", filepath, ret); core_fileclose(file_handle); - storage_heap_free(container_arguments->buffer); + user_free(container_arguments->buffer); return ret; } ret = core_fileclose(file_handle); if (ret < 0) { LOG_ERR("Failed to close file %s: %d", filepath, ret); - storage_heap_free(container_arguments->buffer); + user_free(container_arguments->buffer); return ret; } return 0; @@ -239,12 +230,17 @@ int CS_ctx_init(ocre_cs_ctx *ctx) { return 0; } +#if WASM_MEM_ALLOC_WITH_USER_DATA || WASM_MEM_ALLOC_WITH_USAGE +#error user allocator not compatible with WASM_MEM_ALLOC_WITH_USER_DATA or WASM_MEM_ALLOC_WITH_USAGE +#endif + ocre_container_runtime_status_t CS_runtime_init(ocre_cs_ctx *ctx, ocre_container_init_arguments_t *args) { RuntimeInitArgs init_args; memset(&init_args, 0, sizeof(RuntimeInitArgs)); - init_args.mem_alloc_type = Alloc_With_Pool; - init_args.mem_alloc_option.pool.heap_buf = wamr_heap_buf; - init_args.mem_alloc_option.pool.heap_size = sizeof(wamr_heap_buf); + init_args.mem_alloc_type = Alloc_With_Allocator; + init_args.mem_alloc_option.allocator.malloc_func = user_malloc; + init_args.mem_alloc_option.allocator.free_func = user_free; + init_args.mem_alloc_option.allocator.realloc_func = user_realloc; init_args.native_module_name = "env"; init_args.n_native_symbols = ocre_api_table_size; init_args.native_symbols = ocre_api_table; @@ -266,7 +262,6 @@ ocre_container_runtime_status_t CS_runtime_init(ocre_cs_ctx *ctx, ocre_container #ifdef CONFIG_OCRE_CONTAINER_MESSAGING ocre_messaging_init(); #endif - storage_heap_init(); return RUNTIME_STATUS_INITIALIZED; } @@ -321,7 +316,7 @@ ocre_container_status_t CS_create_container(ocre_container_t *container) { curr_container_arguments->error_buf, sizeof(curr_container_arguments->error_buf)); if (!curr_container_arguments->module) { LOG_ERR("Failed to load WASM module: %s", curr_container_arguments->error_buf); - storage_heap_free(curr_container_arguments->buffer); + user_free(curr_container_arguments->buffer); return CONTAINER_STATUS_ERROR; } @@ -380,7 +375,7 @@ ocre_container_status_t CS_run_container(ocre_container_t *container) { LOG_ERR("Failed to instantiate WASM module: %s, for containerID= %d", curr_container_arguments->error_buf, curr_container_ID); wasm_runtime_unload(curr_container_arguments->module); - storage_heap_free(curr_container_arguments->buffer); + user_free(curr_container_arguments->buffer); return CONTAINER_STATUS_ERROR; } #if defined(CONFIG_OCRE_TIMER) || defined(CONFIG_OCRE_GPIO) || defined(CONFIG_OCRE_SENSORS) || \ @@ -513,7 +508,7 @@ ocre_container_status_t CS_destroy_container(ocre_container_t *container, ocre_c } if (container->ocre_runtime_arguments.buffer) { - storage_heap_free(container->ocre_runtime_arguments.buffer); + user_free(container->ocre_runtime_arguments.buffer); container->ocre_runtime_arguments.buffer = NULL; } From 4b1ee9599f6112f38e27a3cddb84a4fef1f4a87d Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 17 Nov 2025 16:29:38 +0100 Subject: [PATCH 020/234] ocre_mem: remove storage allocator In favor of the user heap mechanism. Signed-off-by: Marco Casaroli --- Kconfig | 7 ------- boards/b_u585i_iot02a.conf | 1 - src/shared/platform/ocre_psram.h | 31 ------------------------------- 3 files changed, 39 deletions(-) delete mode 100644 src/shared/platform/ocre_psram.h diff --git a/Kconfig b/Kconfig index bf2d4a01..722d11f4 100644 --- a/Kconfig +++ b/Kconfig @@ -39,13 +39,6 @@ config OCRE_WAMR_HEAP_BUFFER_SIZE help A static memory allocation for WAMR to use as a heap. -config OCRE_STORAGE_HEAP_BUFFER_SIZE - int "Storage heap buffer size in bytes" - default 500000 - depends on MEMC - help - A static memory allocation for container storage to use as a heap. - config OCRE_CONTAINER_DEFAULT_HEAP_SIZE int "Default value for the container heap size" default 4096 diff --git a/boards/b_u585i_iot02a.conf b/boards/b_u585i_iot02a.conf index 90d47674..3baf394e 100644 --- a/boards/b_u585i_iot02a.conf +++ b/boards/b_u585i_iot02a.conf @@ -9,7 +9,6 @@ CONFIG_MEMC=y # Container defaults CONFIG_MAX_CONTAINERS=5 CONFIG_OCRE_WAMR_HEAP_BUFFER_SIZE=6388608 -CONFIG_OCRE_STORAGE_HEAP_BUFFER_SIZE=2000000 # Bus interfaces CONFIG_GPIO=y diff --git a/src/shared/platform/ocre_psram.h b/src/shared/platform/ocre_psram.h deleted file mode 100644 index 1072b49b..00000000 --- a/src/shared/platform/ocre_psram.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef OCRE_PSRAM -#define OCRE_PSRAM - -// PSRAM configuration - centralized for different platforms -#if defined(CONFIG_MEMC) - // Board-specific PSRAM section attributes - #if defined(CONFIG_BOARD_ARDUINO_PORTENTA_H7) - #define PSRAM_SECTION_ATTR __attribute__((section("SDRAM1"), aligned(32))) - #elif defined(CONFIG_BOARD_B_U585I_IOT02A) - #define PSRAM_SECTION_ATTR __attribute__((section(".stm32_psram"), aligned(32))) - #elif defined(CONFIG_BOARD_MIMXRT1064_EVK) - #define PSRAM_SECTION_ATTR __attribute__((section("SDRAM"), aligned(32))) - #else - #define PSRAM_SECTION_ATTR __attribute__((aligned(32))) - #endif - - PSRAM_SECTION_ATTR - static char storage_heap_buf[CONFIG_OCRE_STORAGE_HEAP_BUFFER_SIZE] = {0}; - - static struct k_heap storage_heap; - #define storage_heap_init() k_heap_init(&storage_heap, storage_heap_buf, CONFIG_OCRE_STORAGE_HEAP_BUFFER_SIZE) - #define storage_heap_alloc(size) k_heap_alloc(&storage_heap, (size), K_SECONDS(1)) - #define storage_heap_free(buffer) k_heap_free(&storage_heap, (void*)buffer) -#else - // No PSRAM - use system malloc - #define storage_heap_init() /* No initialization needed */ - #define storage_heap_alloc(size) malloc(size) - #define storage_heap_free(buffer) free(buffer) -#endif - -#endif /* OCRE_PSRAM*/ From 512523328a53897e59eb079fa493f8f54e8552de Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 17 Nov 2025 16:32:37 +0100 Subject: [PATCH 021/234] wamr: remove OCRE_WAMR_HEAP_BUFFER_SIZE We now use the user heap mechanism. Signed-off-by: Marco Casaroli --- Kconfig | 6 ------ boards/b_u585i_iot02a.conf | 1 - prj.conf | 1 - 3 files changed, 8 deletions(-) diff --git a/Kconfig b/Kconfig index 722d11f4..779dded9 100644 --- a/Kconfig +++ b/Kconfig @@ -33,12 +33,6 @@ config OCRE # Enable the WASM Micro Runtime select WAMR -config OCRE_WAMR_HEAP_BUFFER_SIZE - int "WAMR heap buffer size in bytes" - default 32768 - help - A static memory allocation for WAMR to use as a heap. - config OCRE_CONTAINER_DEFAULT_HEAP_SIZE int "Default value for the container heap size" default 4096 diff --git a/boards/b_u585i_iot02a.conf b/boards/b_u585i_iot02a.conf index 3baf394e..6efe69b4 100644 --- a/boards/b_u585i_iot02a.conf +++ b/boards/b_u585i_iot02a.conf @@ -8,7 +8,6 @@ CONFIG_MEMC=y # Container defaults CONFIG_MAX_CONTAINERS=5 -CONFIG_OCRE_WAMR_HEAP_BUFFER_SIZE=6388608 # Bus interfaces CONFIG_GPIO=y diff --git a/prj.conf b/prj.conf index 519f3f84..51e4fe66 100644 --- a/prj.conf +++ b/prj.conf @@ -64,7 +64,6 @@ CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=-1 # Ocre configuration -CONFIG_OCRE_WAMR_HEAP_BUFFER_SIZE=512000 CONFIG_OCRE_CONTAINER_DEFAULT_HEAP_SIZE=4096 CONFIG_OCRE_CONTAINER_DEFAULT_STACK_SIZE=4096 CONFIG_LOG_TRACE_SHORT_TIMESTAMP=y From a788d12d5c9cc3449272e5e4a90a47129af9154f Mon Sep 17 00:00:00 2001 From: Krisztian <34309983+kr-t@users.noreply.github.com> Date: Wed, 19 Nov 2025 11:09:43 +0100 Subject: [PATCH 022/234] Add shared memory and DNS resolution support (#99) Update wamr's hash to support networking DNS changes. --------- Signed-off-by: Krisztian Szilvasi <34309983+kr-t@users.noreply.github.com> Signed-off-by: Marco Casaroli --- Kconfig | 50 ++++++++++++- .../container_supervisor/cs_sm_impl.c | 71 ++++++++++++++++++- src/shared/platform/posix/ocre_internal.cmake | 1 + .../platform/zephyr/ocre_internal.cmake | 1 + wasm-micro-runtime | 2 +- 5 files changed, 122 insertions(+), 3 deletions(-) diff --git a/Kconfig b/Kconfig index 779dded9..701b0169 100644 --- a/Kconfig +++ b/Kconfig @@ -211,5 +211,53 @@ config OCRE_NETWORKING default n help Enable networking support for containers. - + +config OCRE_SHARED_HEAP + bool "Enable container shared heap support" + default n + help + Enable shared heap support for containers. + +config OCRE_SHARED_HEAP_BUF_SIZE + int "Shared heap buffer size in bytes" + default 65536 + depends on OCRE_SHARED_HEAP + help + Size of the pre-allocated buffer for the shared heap. + This memory is shared between WebAssembly modules. + +choice OCRE_SHARED_HEAP_MODE + prompt "Shared heap mode" + depends on OCRE_SHARED_HEAP + default OCRE_SHARED_HEAP_BUF_VIRTUAL + help + Select the shared heap memory mode: + - Physical: Map physical hardware registers (e.g., GPIO) to WASM address space + - Virtual: Allocate shared heap from regular RAM + +config OCRE_SHARED_HEAP_BUF_PHYSICAL + bool "Physical (hardware register mapping)" + help + Enable physical memory mapping for hardware access. + Maps physical hardware registers (like GPIO at 0x42020000) to WASM address space. + Use this when containers need direct access to hardware peripherals. + +config OCRE_SHARED_HEAP_BUF_VIRTUAL + bool "Virtual (RAM allocation)" + help + Enable virtual shared heap allocated from regular RAM. + Use this for normal inter-module communication without + direct hardware access. + +endchoice + +config OCRE_SHARED_HEAP_BUF_ADDRESS + hex "Shared heap buffer address" + default 0x00 + depends on OCRE_SHARED_HEAP + help + Shared heap buffer address. + - For physical mode: Physical address of hardware registers + - For virtual mode: Leave as 0x00 to auto-allocate from RAM + endmenu diff --git a/src/ocre/components/container_supervisor/cs_sm_impl.c b/src/ocre/components/container_supervisor/cs_sm_impl.c index c4addb56..29b2cefb 100644 --- a/src/ocre/components/container_supervisor/cs_sm_impl.c +++ b/src/ocre/components/container_supervisor/cs_sm_impl.c @@ -64,6 +64,14 @@ static size_t ocre_get_available_memory(void) { } #endif +#ifdef CONFIG_OCRE_SHARED_HEAP +// Shared heap for memory-mapped access +wasm_shared_heap_t _shared_heap = NULL; +#ifdef CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL +uint8 preallocated_buf[CONFIG_OCRE_SHARED_HEAP_BUF_SIZE]; +#endif +#endif + static bool validate_container_memory(ocre_container_t *container) { #ifdef CONFIG_OCRE_MEMORY_CHECK_ENABLED size_t requested_heap = container->ocre_container_data.heap_size; @@ -262,6 +270,31 @@ ocre_container_runtime_status_t CS_runtime_init(ocre_cs_ctx *ctx, ocre_container #ifdef CONFIG_OCRE_CONTAINER_MESSAGING ocre_messaging_init(); #endif +#ifdef CONFIG_OCRE_SHARED_HEAP + SharedHeapInitArgs heap_init_args; + memset(&heap_init_args, 0, sizeof(heap_init_args)); + +#ifdef CONFIG_OCRE_SHARED_HEAP_BUF_PHYSICAL + // Physical mode - map hardware register address + heap_init_args.pre_allocated_addr = (void *)CONFIG_OCRE_SHARED_HEAP_BUF_ADDRESS; + LOG_INF("Creating physical memory mapping at 0x%08X (hardware registers)", + CONFIG_OCRE_SHARED_HEAP_BUF_ADDRESS); +#elif CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL + // Virtual mode - allocate from RAM + heap_init_args.pre_allocated_addr = preallocated_buf; + LOG_INF("Creating virtual shared heap in RAM, size=%d bytes", + CONFIG_OCRE_SHARED_HEAP_BUF_SIZE); +#endif + heap_init_args.size = CONFIG_OCRE_SHARED_HEAP_BUF_SIZE; + _shared_heap = wasm_runtime_create_shared_heap(&heap_init_args); + + if (!_shared_heap) { + LOG_ERR("Create preallocated shared heap failed"); + return RUNTIME_STATUS_ERROR; + } +#endif + + storage_heap_init(); return RUNTIME_STATUS_INITIALIZED; } @@ -347,6 +380,15 @@ ocre_container_status_t CS_run_container(ocre_container_t *container) { "0.0.0.0/0", }; wasm_runtime_set_wasi_addr_pool(curr_container_arguments->module, addr_pool, ADDRESS_POOL_SIZE); + /** + * Configure which domain names a WebAssembly module is allowed to resolve via DNS lookups + * ns_lookup_pool: An array of domain name patterns (e.g., "example.com", "*.example.com", or "*" for any domain) + */ + + const char *ns_lookup_pool[] = { + "*" + }; + wasm_runtime_set_wasi_ns_lookup_pool(curr_container_arguments->module, ns_lookup_pool, sizeof(ns_lookup_pool) / sizeof(ns_lookup_pool[0])); #endif #ifdef CONFIG_OCRE_CONTAINER_FILESYSTEM @@ -382,8 +424,35 @@ ocre_container_status_t CS_run_container(ocre_container_t *container) { defined(CONFIG_OCRE_CONTAINER_MESSAGING) ocre_register_module(curr_container_arguments->module_inst); #endif - } +#ifdef CONFIG_OCRE_SHARED_HEAP + LOG_INF("Attaching shared heap to container %d", curr_container_ID); + /* attach module instance to the shared heap */ + if (!wasm_runtime_attach_shared_heap(curr_container_arguments->module_inst, _shared_heap)) { + LOG_ERR("Attach shared heap failed."); + return CONTAINER_STATUS_ERROR; + } +#ifdef CONFIG_OCRE_SHARED_HEAP_BUF_PHYSICAL + // For physical mode, get the base address from the shared heap itself + // The WASM address space already knows about the physical mapping + uint32 shared_heap_base_addr = wasm_runtime_addr_native_to_app( + curr_container_arguments->module_inst, + (void*)CONFIG_OCRE_SHARED_HEAP_BUF_ADDRESS); + LOG_INF("Physical shared heap base address in app: 0x%x", shared_heap_base_addr); +#elif CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL + // For virtual mode, convert the allocated buffer address + uint32 shared_heap_base_addr = wasm_runtime_addr_native_to_app( + curr_container_arguments->module_inst, + preallocated_buf); + LOG_INF("Virtual shared heap base address in app: 0x%x", shared_heap_base_addr); +#endif + + if (shared_heap_base_addr == 0) { + LOG_ERR("Failed to get shared heap WASM address!"); + return CONTAINER_STATUS_ERROR; + } +#endif + } core_mutex_lock(&container_mutex); int thread_idx = get_available_thread(); if (thread_idx == -1) { diff --git a/src/shared/platform/posix/ocre_internal.cmake b/src/shared/platform/posix/ocre_internal.cmake index 03ec062b..675dbb3e 100644 --- a/src/shared/platform/posix/ocre_internal.cmake +++ b/src/shared/platform/posix/ocre_internal.cmake @@ -43,6 +43,7 @@ set (WAMR_BUILD_LIBC_WASI 1) set (WAMR_BUILD_LIB_PTHREAD 1) set (WAMR_BUILD_REF_TYPES 1) set (WASM_ENABLE_LOG 1) +set (WAMR_BUILD_SHARED_HEAP 1) if (NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_POOL) set (WAMR_BUILD_GLOBAL_HEAP_POOL 1) diff --git a/src/shared/platform/zephyr/ocre_internal.cmake b/src/shared/platform/zephyr/ocre_internal.cmake index 38fbcd16..cccf6375 100644 --- a/src/shared/platform/zephyr/ocre_internal.cmake +++ b/src/shared/platform/zephyr/ocre_internal.cmake @@ -40,6 +40,7 @@ set(WAMR_BUILD_LIBC_WASI 1) set(WAMR_BUILD_LIB_PTHREAD 1) set(WAMR_BUILD_REF_TYPES 1) set(WASM_ENABLE_LOG 1) +set (WAMR_BUILD_SHARED_HEAP 1) if(NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_POOL) set(WAMR_BUILD_GLOBAL_HEAP_POOL 1) diff --git a/wasm-micro-runtime b/wasm-micro-runtime index ce279ef9..c9cf93fb 160000 --- a/wasm-micro-runtime +++ b/wasm-micro-runtime @@ -1 +1 @@ -Subproject commit ce279ef9c45158c6fd4c6816f87581b1175c3818 +Subproject commit c9cf93fb10fe31e229658937a9afa2fbb41fb009 From 96e6456bf4b0706871ce774b13df405961d95ab5 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 15 Dec 2025 20:57:25 +0100 Subject: [PATCH 023/234] build(devcontainer): Dockerfile This docker image will be used in the CI and the devcontainer. Signed-off-by: Marco Casaroli --- .devcontainer/linux/Dockerfile | 49 ++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 .devcontainer/linux/Dockerfile diff --git a/.devcontainer/linux/Dockerfile b/.devcontainer/linux/Dockerfile new file mode 100644 index 00000000..4758ab3c --- /dev/null +++ b/.devcontainer/linux/Dockerfile @@ -0,0 +1,49 @@ +FROM ubuntu:24.04 + +ARG USERNAME=ocre-dev +ARG USER_UID=1000 +ARG USER_GID=$USER_UID + +ARG NODE_MAJOR=20 +ARG WASI_SDK_VERSION=29 + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + gcc \ + git \ + gpg \ + make \ + build-essential \ + cmake \ + cppcheck \ + clang \ + clang-tools \ + llvm \ + net-tools \ + jq \ + && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \ + echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list && \ + apt-get update && apt-get install -y --no-install-recommends \ + nodejs \ + && apt-get clean -y\ + && update-alternatives --install /usr/bin/python python /usr/bin/python3 50 + +# Install wasi-sdk +RUN mkdir /opt/wasi-sdk && \ + curl -sSL https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-$WASI_SDK_VERSION/wasi-sdk-$WASI_SDK_VERSION.0-$(uname -m | sed s/aarch64/arm64/)-linux.tar.gz | \ + tar zxvf - --strip-components=1 -C /opt/wasi-sdk + +# Accomodate the user for devcontainer +RUN (userdel -r $USERNAME ; userdel -r `id -nu $USER_UID` ; groupdel `id -ng $USER_GID`) || true \ + && groupadd --gid $USER_GID $USERNAME \ + && useradd --uid $USER_UID --gid $USER_GID -m $USERNAME -s /bin/bash \ + && apt-get update \ + && apt-get install -y sudo \ + && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \ + && chmod 0440 /etc/sudoers.d/$USERNAME && echo oi + +USER $USERNAME +WORKDIR /home/ocre-dev \ No newline at end of file From c38be2be9aa4b87e6c64700ac38873f24a30a564 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 15 Dec 2025 20:33:53 +0100 Subject: [PATCH 024/234] ci: build devcontainer Signed-off-by: Marco Casaroli --- .github/workflows/devcontainer-linux.yml | 68 ++++++++++++++++++++++++ .github/workflows/main.yml | 24 +++++++++ 2 files changed, 92 insertions(+) create mode 100644 .github/workflows/devcontainer-linux.yml create mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/devcontainer-linux.yml b/.github/workflows/devcontainer-linux.yml new file mode 100644 index 00000000..93c5920e --- /dev/null +++ b/.github/workflows/devcontainer-linux.yml @@ -0,0 +1,68 @@ +name: Linux devcontainer + +on: + workflow_call: + inputs: + ref: + type: string + required: false + outputs: + devcontainer-tag: + value: ${{ jobs.necessary.outputs.devcontainer-tag }} + +jobs: + necessary: + name: Necessary? + runs-on: ubuntu-24.04 + outputs: + build: ${{ steps.changed-files.outputs.all_changed_and_modified_files != '' }} + devcontainer-tag: ${{ steps.devcontainer-tag.outputs.tag }} + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ inputs.ref }} + + - uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 + id: changed-files + with: + exclude_submodules: true + files: | + .devcontainer/linux/Dockerfile + + - name: Set devcontainer tag + id: devcontainer-tag + run: | + tag=${{ steps.changed-files.outputs.all_changed_and_modified_files != '' && github.ref != 'refs/heads/main' && github.sha || 'latest' }} + echo "tag=$tag" >> $GITHUB_OUTPUT + + build-push: + name: Build and push + if: ${{ needs.necessary.outputs.build == 'true' }} + needs: + - necessary + runs-on: ubuntu-24.04 + + steps: + - name: Checkout the code + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Github Registry + uses: docker/login-action@v3 + with: + username: ${{ github.actor }} + password: ${{ github.token }} + registry: ghcr.io + + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: .devcontainer/linux + file: .devcontainer/linux/Dockerfile + platforms: linux/amd64,linux/arm64 + push: true + tags: ghcr.io/${{ github.repository }}/devcontainer-linux:${{ needs.necessary.outputs.devcontainer-tag }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000..4ef62e0e --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,24 @@ +name: Main + +on: + pull_request: + types: + - opened + - synchronize + - reopened + - labeled + push: + branches: + - main + +concurrency: + group: ${{ github.repository }}-${{ github.workflow }}@main-${{ github.ref }} + cancel-in-progress: true + +jobs: + builder: + name: Linux devcontainer + uses: ./.github/workflows/devcontainer-linux.yml + secrets: inherit + with: + ref: ${{ github.sha }} From aa7ad4d441918193fbee3154265f3804f1399f0b Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 15 Dec 2025 21:06:59 +0100 Subject: [PATCH 025/234] ci(devcontainer): add permission to write packages We will upload the images for the CI there. Signed-off-by: Marco Casaroli --- .github/workflows/main.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4ef62e0e..149fefa9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -20,5 +20,8 @@ jobs: name: Linux devcontainer uses: ./.github/workflows/devcontainer-linux.yml secrets: inherit + permissions: + contents: read + packages: write with: ref: ${{ github.sha }} From fdc69f568880369db2e80afca9c8ad1023e6ffa2 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 15 Dec 2025 20:33:53 +0100 Subject: [PATCH 026/234] ci: build devcontainer Signed-off-by: Marco Casaroli --- ocre-sdk | 1 + 1 file changed, 1 insertion(+) create mode 160000 ocre-sdk diff --git a/ocre-sdk b/ocre-sdk new file mode 160000 index 00000000..6f53f2ff --- /dev/null +++ b/ocre-sdk @@ -0,0 +1 @@ +Subproject commit 6f53f2ffa46f61413846514fdf9a4ebeaa715518 From 34f659eb501d95e356ab3da0aa4c13c3121c0d2a Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 16 Dec 2025 19:26:47 +0100 Subject: [PATCH 027/234] chore(west): update manifest Pin to upstream Zephyr and review needed modules. Signed-off-by: Marco Casaroli --- west.yml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/west.yml b/west.yml index cee4e7bb..5b5d27f5 100644 --- a/west.yml +++ b/west.yml @@ -1,19 +1,17 @@ manifest: projects: - name: zephyr - revision: staging - url: https://github.com/project-ocre/zephyr + revision: v4.3.0 + url: https://github.com/zephyrproject-rtos/zephyr west-commands: scripts/west-commands.yml import: name-allowlist: - littlefs - picolibc - - mcuboot - - zcbor - hal_stm32 - hal_st - - mbedtls + - hal_nordic + - hal_rpi_pico - cmsis_6 - self: - path: application + path: ocre-runtime From 81012a2d30c5247f7db6dff18a3201fd6178e84f Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 16 Dec 2025 21:52:31 +0100 Subject: [PATCH 028/234] build(devcontainer): add Zephyr The Zephyr devcontainer already includes the python modules, wasi-sdk and the Zephyr SDK Signed-off-by: Marco Casaroli --- .devcontainer/zephyr/Dockerfile | 96 ++++++++++++++++++++++++++ .devcontainer/zephyr/devcontainer.json | 8 +++ 2 files changed, 104 insertions(+) create mode 100644 .devcontainer/zephyr/Dockerfile create mode 100644 .devcontainer/zephyr/devcontainer.json diff --git a/.devcontainer/zephyr/Dockerfile b/.devcontainer/zephyr/Dockerfile new file mode 100644 index 00000000..9664529e --- /dev/null +++ b/.devcontainer/zephyr/Dockerfile @@ -0,0 +1,96 @@ +FROM ubuntu:24.04 AS base + +ARG USERNAME=ocre-dev +ARG USER_UID=1000 +ARG USER_GID=$USER_UID + +ARG NODE_MAJOR=20 +ARG WASI_SDK_VERSION=29 + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y --no-install-recommends \ + build-essential \ + ca-certificates \ + ccache \ + clang \ + clang-format \ + clang-tools \ + cmake \ + cppcheck \ + curl \ + device-tree-compiler \ + dfu-util \ + file \ + gcc \ + git \ + gperf \ + gpg \ + jq \ + libmagic1 \ + libsdl2-dev \ + llvm \ + make \ + net-tools \ + ninja-build \ + python3-dev \ + python3-venv \ + python3-tk \ + wget \ + xz-utils \ + && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \ + echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list && \ + apt-get update && apt-get install -y --no-install-recommends \ + nodejs \ + && apt-get clean -y\ + && update-alternatives --install /usr/bin/python python /usr/bin/python3 50 + +# Install wasi-sdk +RUN mkdir /opt/wasi-sdk && \ + curl -sSL https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-$WASI_SDK_VERSION/wasi-sdk-$WASI_SDK_VERSION.0-$(uname -m | sed s/aarch64/arm64/)-linux.tar.gz | \ + tar zxvf - --strip-components=1 -C /opt/wasi-sdk + +# Accomodate the user for devcontainer +RUN (userdel -r $USERNAME ; userdel -r `id -nu $USER_UID` ; groupdel `id -ng $USER_GID`) || true \ + && groupadd --gid $USER_GID $USERNAME \ + && useradd --uid $USER_UID --gid $USER_GID -m $USERNAME -s /bin/bash \ + && apt-get update \ + && apt-get install -y sudo \ + && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \ + && chmod 0440 /etc/sudoers.d/$USERNAME + +USER $USERNAME + +WORKDIR /home/ocre-dev + +RUN python -m venv .venv && \ + . .venv/bin/activate && \ + pip install \ + west \ + littlefs-python + +# Install the SDK on a separate stage to avoid layer cluttering + +FROM base AS zephyr-sdk + +RUN mkdir -p /tmp/zephyrproject/ocre-runtime + +COPY west.yml /tmp/zephyrproject/ocre-runtime/west.yml + +RUN . .venv/bin/activate && \ + cd /tmp/zephyrproject && \ + west init -l ocre-runtime && \ + west update -n zephyr && \ + west packages pip --install && \ + west sdk install -t \ + x86_64-zephyr-elf \ + aarch64-zephyr-elf \ + arm-zephyr-eabi + +FROM base AS ocre-dev + +COPY --from=zephyr-sdk /home/ocre-dev /home/ocre-dev + +RUN printf "\n%s\n" '. ~/.venv/bin/activate' >> /home/ocre-dev/.bashrc + +WORKDIR /home/ocre-dev/zephyrproject diff --git a/.devcontainer/zephyr/devcontainer.json b/.devcontainer/zephyr/devcontainer.json new file mode 100644 index 00000000..2ca94ddb --- /dev/null +++ b/.devcontainer/zephyr/devcontainer.json @@ -0,0 +1,8 @@ +{ + "build": { + "dockerfile": "Dockerfile", + "context": "../.." + }, + "remoteUser": "ocre-dev", + "postCreateCommand": "sudo chown ocre-dev /workspaces" +} From 9d5d506a407fd15bf0c2fb3a3270e97d6714fc70 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 16 Dec 2025 21:55:00 +0100 Subject: [PATCH 029/234] ci(devcontainer): Zephyr Build the Zephyr devcontainer like we do with Linux Signed-off-by: Marco Casaroli --- .github/workflows/devcontainer-zephyr.yml | 69 +++++++++++++++++++++++ .github/workflows/main.yml | 10 ++++ 2 files changed, 79 insertions(+) create mode 100644 .github/workflows/devcontainer-zephyr.yml diff --git a/.github/workflows/devcontainer-zephyr.yml b/.github/workflows/devcontainer-zephyr.yml new file mode 100644 index 00000000..88866f0a --- /dev/null +++ b/.github/workflows/devcontainer-zephyr.yml @@ -0,0 +1,69 @@ +name: Zephyr devcontainer + +on: + workflow_call: + inputs: + ref: + type: string + required: false + outputs: + devcontainer-tag: + value: ${{ jobs.necessary.outputs.devcontainer-tag }} + +jobs: + necessary: + name: Necessary? + runs-on: ubuntu-24.04 + outputs: + build: ${{ steps.changed-files.outputs.all_changed_and_modified_files != '' }} + devcontainer-tag: ${{ steps.devcontainer-tag.outputs.tag }} + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ inputs.ref }} + + - uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 + id: changed-files + with: + exclude_submodules: true + files: | + .devcontainer/zephyr/Dockerfile + west.yml + + - name: Set devcontainer tag + id: devcontainer-tag + run: | + tag=${{ steps.changed-files.outputs.all_changed_and_modified_files != '' && github.ref != 'refs/heads/main' && github.sha || 'latest' }} + echo "tag=$tag" >> $GITHUB_OUTPUT + + build-push: + name: Build and push + if: ${{ needs.necessary.outputs.build == 'true' }} + needs: + - necessary + runs-on: ubuntu-24.04 + + steps: + - name: Checkout the code + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Github Registry + uses: docker/login-action@v3 + with: + username: ${{ github.actor }} + password: ${{ github.token }} + registry: ghcr.io + + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: . + file: .devcontainer/zephyr/Dockerfile + platforms: linux/amd64,linux/arm64 + push: true + tags: ghcr.io/${{ github.repository }}/devcontainer-zephyr:${{ needs.necessary.outputs.devcontainer-tag }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 149fefa9..00526b17 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -25,3 +25,13 @@ jobs: packages: write with: ref: ${{ github.sha }} + + zephyr-devcontainer: + name: Zephyr devcontainer + uses: ./.github/workflows/devcontainer-zephyr.yml + secrets: inherit + permissions: + contents: read + packages: write + with: + ref: ${{ github.sha }} From c9f93d1e71f5fcd1e1b2e5b08afc2f4e48d27978 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 16 Dec 2025 22:09:55 +0100 Subject: [PATCH 030/234] build(devcontainer/linux): add clang-format Signed-off-by: Marco Casaroli --- .devcontainer/linux/Dockerfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.devcontainer/linux/Dockerfile b/.devcontainer/linux/Dockerfile index 4758ab3c..025432d2 100644 --- a/.devcontainer/linux/Dockerfile +++ b/.devcontainer/linux/Dockerfile @@ -20,6 +20,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ cmake \ cppcheck \ clang \ + clang-format \ clang-tools \ llvm \ net-tools \ @@ -43,7 +44,7 @@ RUN (userdel -r $USERNAME ; userdel -r `id -nu $USER_UID` ; groupdel `id -ng $US && apt-get update \ && apt-get install -y sudo \ && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \ - && chmod 0440 /etc/sudoers.d/$USERNAME && echo oi + && chmod 0440 /etc/sudoers.d/$USERNAME USER $USERNAME -WORKDIR /home/ocre-dev \ No newline at end of file +WORKDIR /home/ocre-dev From 90ce00c98cbec955b2a3d333b80815800c35ec8c Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 16 Dec 2025 22:34:51 +0100 Subject: [PATCH 031/234] ci(devcontainer/zephyr): bump timeout The default timeout of 30 minuts is too low. Signed-off-by: Marco Casaroli --- .github/workflows/devcontainer-zephyr.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/devcontainer-zephyr.yml b/.github/workflows/devcontainer-zephyr.yml index 88866f0a..3ed33315 100644 --- a/.github/workflows/devcontainer-zephyr.yml +++ b/.github/workflows/devcontainer-zephyr.yml @@ -40,6 +40,7 @@ jobs: build-push: name: Build and push + timeout-minutes: 60 if: ${{ needs.necessary.outputs.build == 'true' }} needs: - necessary From b943f074d36d6b164ea11658ef18280d587e7e67 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 16 Dec 2025 23:08:58 +0100 Subject: [PATCH 032/234] ci(devontainer): do not build multiplatform It is slow, and we do not use it in the CI. Signed-off-by: Marco Casaroli --- .github/workflows/devcontainer-linux.yml | 1 - .github/workflows/devcontainer-zephyr.yml | 1 - 2 files changed, 2 deletions(-) diff --git a/.github/workflows/devcontainer-linux.yml b/.github/workflows/devcontainer-linux.yml index 93c5920e..40288c88 100644 --- a/.github/workflows/devcontainer-linux.yml +++ b/.github/workflows/devcontainer-linux.yml @@ -63,6 +63,5 @@ jobs: with: context: .devcontainer/linux file: .devcontainer/linux/Dockerfile - platforms: linux/amd64,linux/arm64 push: true tags: ghcr.io/${{ github.repository }}/devcontainer-linux:${{ needs.necessary.outputs.devcontainer-tag }} diff --git a/.github/workflows/devcontainer-zephyr.yml b/.github/workflows/devcontainer-zephyr.yml index 3ed33315..11123457 100644 --- a/.github/workflows/devcontainer-zephyr.yml +++ b/.github/workflows/devcontainer-zephyr.yml @@ -65,6 +65,5 @@ jobs: with: context: . file: .devcontainer/zephyr/Dockerfile - platforms: linux/amd64,linux/arm64 push: true tags: ghcr.io/${{ github.repository }}/devcontainer-zephyr:${{ needs.necessary.outputs.devcontainer-tag }} From eb18115104c00fb35e9926876130e1652b533ecc Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 16 Dec 2025 23:33:49 +0100 Subject: [PATCH 033/234] ci: pass github UID and GID Github actions uses UID 1001 and GID 127 for running the docker build. The container must be compatible. Yet, we do not want to break the default build of the devcontainer using vscode of the devcontainer-cli. Signed-off-by: Marco Casaroli --- .github/workflows/devcontainer-linux.yml | 3 +++ .github/workflows/devcontainer-zephyr.yml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/.github/workflows/devcontainer-linux.yml b/.github/workflows/devcontainer-linux.yml index 40288c88..18cc692b 100644 --- a/.github/workflows/devcontainer-linux.yml +++ b/.github/workflows/devcontainer-linux.yml @@ -65,3 +65,6 @@ jobs: file: .devcontainer/linux/Dockerfile push: true tags: ghcr.io/${{ github.repository }}/devcontainer-linux:${{ needs.necessary.outputs.devcontainer-tag }} + build-args: | + USER_UID=1001 + USER_GID=127 diff --git a/.github/workflows/devcontainer-zephyr.yml b/.github/workflows/devcontainer-zephyr.yml index 11123457..0066b179 100644 --- a/.github/workflows/devcontainer-zephyr.yml +++ b/.github/workflows/devcontainer-zephyr.yml @@ -67,3 +67,6 @@ jobs: file: .devcontainer/zephyr/Dockerfile push: true tags: ghcr.io/${{ github.repository }}/devcontainer-zephyr:${{ needs.necessary.outputs.devcontainer-tag }} + build-args: | + USER_UID=1001 + USER_GID=127 From 20c3f791e808193af366211393a57c2f327dddd9 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Fri, 19 Dec 2025 16:50:24 +0100 Subject: [PATCH 034/234] chore: west.yml license banner Signed-off-by: Marco Casaroli --- west.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/west.yml b/west.yml index 5b5d27f5..a746f7fa 100644 --- a/west.yml +++ b/west.yml @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + manifest: projects: - name: zephyr From e759c28138f7a2ba5e665b28826c22ef8c39404c Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 8 Dec 2025 16:34:40 +0100 Subject: [PATCH 035/234] big refactor Signed-off-by: Marco Casaroli --- .clang-format | 17 +- .clangd | 2 + .gitignore | 4 + .gitmodules | 6 + .vscode/launch.json | 19 +- .zed/debug.json | 22 + .zed/tasks.json | 16 + CMakeLists.txt | 92 +- Dockerfile | 79 ++ TODO.txt | 40 + boards/b_u585i_iot02a.conf | 57 - boards/enc28j60.conf | 3 - boards/enc28j60.overlay | 11 - boards/native_sim.conf | 35 - boards/native_sim.overlay | 39 - cmake/input_file.cmake | 19 + cmake/state_information.cmake | 17 + cmake/wamr.cmake | 46 + modules/modules.cmake | 1 - prj.conf | 89 -- src/ocre/CMakeLists.txt | 65 + src/ocre/api/ocre_api.c | 152 --- src/ocre/api/ocre_common.c | 389 ------ src/ocre/component/component.c | 21 - src/ocre/component/component.h | 30 - .../component_supervisor.yaml | 11 - .../components/container_supervisor/cs_main.c | 48 - .../components/container_supervisor/cs_sm.c | 169 --- .../components/container_supervisor/cs_sm.h | 50 - .../container_supervisor/cs_sm_impl.c | 612 --------- .../container_supervisor/cs_sm_impl.h | 119 -- .../container_supervisor/message_types.h | 33 - src/ocre/container.c | 584 +++++++++ src/ocre/container.h | 8 + src/ocre/context.c | 335 +++++ src/ocre/context.h | 6 + src/ocre/include/ocre/ocre.h | 81 ++ src/ocre/include/uthash/utarray.h | 258 ++++ src/ocre/include/uthash/uthash.h | 1137 +++++++++++++++++ src/ocre/include/uthash/utlist.h | 1076 ++++++++++++++++ src/ocre/include/uthash/utringbuffer.h | 108 ++ src/ocre/include/uthash/utstack.h | 88 ++ src/ocre/include/uthash/utstring.h | 407 ++++++ src/ocre/ocre.c | 129 ++ src/ocre/ocre.h | 26 +- .../ocre_container_runtime.c | 135 -- .../ocre_container_runtime.h | 212 --- src/ocre/ocre_messaging/ocre_messaging.c | 274 ---- src/ocre/ocre_timers/ocre_timer.c | 255 ---- src/ocre/shell/ocre_shell.c | 152 --- src/ocre/shell/ocre_shell.h | 22 - src/ocre/sm/sm.c | 94 -- src/ocre/sm/sm.h | 54 - src/ocre/unique_random_id.c | 47 + src/ocre/unique_random_id.h | 3 + src/ocre/util/string_array.c | 109 ++ src/ocre/util/string_array.h | 6 + src/ocre/utils/c-smf/CMakeLists.txt | 15 - src/ocre/utils/c-smf/LICENSE | 201 --- src/ocre/utils/c-smf/README.md | 61 - src/ocre/utils/c-smf/smf/CMakeLists.txt | 16 - src/ocre/utils/c-smf/smf/smf.c | 421 ------ src/ocre/utils/c-smf/smf/smf.h | 192 --- src/ocre/utils/c-smf/test/CMakeLists.txt | 13 - src/ocre/utils/c-smf/test/test.c | 73 -- src/ocre/version.h | 1 + src/platform/include/ocre/platform/file.h | 4 + src/platform/include/ocre/platform/memory.h | 6 + src/platform/posix/CMakeLists.txt | 14 + src/platform/posix/file_alloc_fread.c | 102 ++ src/platform/posix/file_alloc_read.c | 95 ++ src/platform/posix/file_mmap.c | 89 ++ .../posix/include/ocre/platform/config.h | 23 + .../posix/include/ocre/platform/log.h | 8 + src/platform/posix/memory.c | 22 + src/platform/zephyr/CMakeLists.txt | 18 + .../zephyr/include/ocre/platform/config.h | 1 + .../zephyr/include/ocre/platform/log.h | 1 + src/platform/zephyr/memory.c | 49 + src/runtime/CMakeLists.txt | 11 + src/runtime/include/ocre/runtime/vtable.h | 20 + src/runtime/wamr/CMakeLists.txt | 21 + .../wamr/include/ocre/runtime/wamr/wamr.h | 8 + src/runtime/wamr/ocre_api/CMakeLists.txt | 29 + src/runtime/wamr/ocre_api/core/core_eventq.c | 79 ++ .../wamr/ocre_api/core/core_external.h} | 33 +- .../wamr/ocre_api/core/core_internal.h | 167 +++ .../wamr/ocre_api/core/core_memory.c} | 33 +- src/runtime/wamr/ocre_api/core/core_misc.c | 60 + src/runtime/wamr/ocre_api/core/core_mutex.c | 33 + src/runtime/wamr/ocre_api/core/core_slist.c | 38 + src/runtime/wamr/ocre_api/core/core_timer.c | 59 + src/runtime/wamr/ocre_api/ocre_api.c | 158 +++ .../api => runtime/wamr/ocre_api}/ocre_api.h | 12 +- src/runtime/wamr/ocre_api/ocre_common.c | 385 ++++++ .../wamr/ocre_api}/ocre_common.h | 109 +- .../wamr/ocre_api}/ocre_gpio/ocre_gpio.c | 8 +- .../wamr/ocre_api}/ocre_gpio/ocre_gpio.h | 0 .../ocre_api/ocre_messaging/ocre_messaging.c | 280 ++++ .../ocre_api}/ocre_messaging/ocre_messaging.h | 15 +- .../ocre_sensors/custom,rng-sensor.yaml | 0 .../ocre_api}/ocre_sensors/ocre_sensors.c | 2 +- .../ocre_api}/ocre_sensors/ocre_sensors.h | 0 .../wamr/ocre_api}/ocre_sensors/rng_sensor.c | 0 .../wamr/ocre_api}/ocre_sensors/rng_sensor.h | 0 .../wamr/ocre_api}/ocre_sensors/usage.md | 0 .../wamr/ocre_api/ocre_timers/ocre_timer.c | 263 ++++ .../wamr/ocre_api}/ocre_timers/ocre_timer.h | 1 - .../wamr/ocre_api}/utils/strlcat.c | 45 +- .../wamr/ocre_api/utils/strlcat.h} | 12 - src/runtime/wamr/wamr.c | 377 ++++++ src/samples-mini/posix/main.c | 114 -- src/samples/bash_runtime/posix/CMakeLists.txt | 21 + .../bash_runtime/posix/bash/CMakeLists.txt | 18 + src/samples/bash_runtime/posix/bash/bash.c | 182 +++ .../bash/include/ocre/runtime/bash/bash.h | 8 + src/samples/bash_runtime/posix/main.c | 87 ++ src/samples/demo/main.c | 147 +++ src/samples/demo/posix/CMakeLists.txt | 19 + src/samples/demo/zephyr/CMakeLists.txt | 21 + .../boards/pico_plus2_rp2350b_m33_w.conf | 2 + .../boards/pico_plus2_rp2350b_m33_w.overlay | 29 + src/samples/demo/zephyr/prj.conf | 22 + src/samples/mini/main.c | 47 + src/samples/mini/posix/CMakeLists.txt | 19 + src/samples/mini/zephyr/CMakeLists.txt | 21 + .../boards/pico_plus2_rp2350b_m33_w.conf | 2 + .../boards/pico_plus2_rp2350b_m33_w.overlay | 29 + src/samples/mini/zephyr/prj.conf | 15 + src/samples/readline/posix/CMakeLists.txt | 38 + src/samples/readline/posix/ocre.c | 56 + src/samples/supervisor/zephyr/CMakeLists.txt | 29 + .../zephyr/boards/b_u585i_iot02a.conf | 2 + .../zephyr/boards}/b_u585i_iot02a.overlay | 20 +- .../boards/pico_plus2_rp2350b_m33_w.conf | 6 + .../boards/pico_plus2_rp2350b_m33_w.overlay | 29 + .../pico_plus2_rp2350b_m33_w_mcuboot.conf | 6 + src/samples/supervisor/zephyr/prj.conf | 48 + src/samples/supervisor/zephyr/service.c | 27 + src/samples/supervisor/zephyr/shell.c | 22 + src/shared/platform/posix/core_eventq.c | 74 -- src/shared/platform/posix/core_fs.c | 160 --- src/shared/platform/posix/core_internal.h | 289 ----- src/shared/platform/posix/core_memory.c | 30 - src/shared/platform/posix/core_misc.c | 56 - src/shared/platform/posix/core_mq.c | 65 - src/shared/platform/posix/core_mutex.c | 27 - src/shared/platform/posix/core_slist.c | 34 - src/shared/platform/posix/core_thread.c | 77 -- src/shared/platform/posix/core_timer.c | 52 - src/shared/platform/posix/ocre_internal.cmake | 117 -- src/shared/platform/zephyr/core_eventq.c | 64 - src/shared/platform/zephyr/core_fs.c | 270 ---- src/shared/platform/zephyr/core_internal.h | 209 --- src/shared/platform/zephyr/core_memory.c | 49 - src/shared/platform/zephyr/core_misc.c | 17 - src/shared/platform/zephyr/core_mq.c | 32 - src/shared/platform/zephyr/core_mutex.c | 28 - src/shared/platform/zephyr/core_thread.c | 35 - src/shared/platform/zephyr/core_timer.c | 37 - .../platform/zephyr/ocre_internal.cmake | 125 -- src/shell/CMakeLists.txt | 37 + src/shell/command.h | 6 + src/shell/container.c | 68 + src/shell/container.h | 3 + src/shell/container/create.c | 153 +++ src/shell/container/create.h | 3 + src/shell/container/inspect.c | 25 + src/shell/container/inspect.h | 3 + src/shell/container/kill.c | 36 + src/shell/container/kill.h | 3 + src/shell/container/ps.c | 113 ++ src/shell/container/ps.h | 3 + src/shell/container/rm.c | 36 + src/shell/container/rm.h | 3 + src/shell/container/start.c | 37 + src/shell/container/start.h | 3 + src/shell/container/stop.c | 25 + src/shell/container/stop.h | 3 + src/shell/container/wait.c | 44 + src/shell/container/wait.h | 3 + src/shell/image.c | 43 + src/shell/image.h | 3 + src/shell/image/ls.c | 202 +++ src/shell/image/ls.h | 3 + src/shell/image/pull.c | 29 + src/shell/image/pull.h | 3 + src/shell/image/rm.c | 44 + src/shell/image/rm.h | 3 + src/shell/include/ocre/shell/shell.h | 3 + src/shell/sha256/LICENSE | 21 + src/shell/sha256/sha256.c | 182 +++ src/shell/sha256/sha256.h | 99 ++ src/shell/shell.c | 92 ++ tools/automsg | 116 -- wasm-micro-runtime | 2 +- zephyr/CMakeLists.txt | 27 + Kconfig => zephyr/Kconfig | 384 +++--- zephyr/module.yml | 6 +- zephyr/user_data.cmake | 28 + zephyr/wamr copy.cmake | 63 + zephyr/wamr.cmake | 62 + 202 files changed, 9978 insertions(+), 6579 deletions(-) create mode 100644 .clangd create mode 100644 .zed/debug.json create mode 100644 .zed/tasks.json create mode 100644 Dockerfile create mode 100644 TODO.txt delete mode 100644 boards/b_u585i_iot02a.conf delete mode 100644 boards/enc28j60.conf delete mode 100644 boards/enc28j60.overlay delete mode 100644 boards/native_sim.conf delete mode 100644 boards/native_sim.overlay create mode 100644 cmake/input_file.cmake create mode 100644 cmake/state_information.cmake create mode 100644 cmake/wamr.cmake delete mode 100644 modules/modules.cmake delete mode 100644 prj.conf create mode 100644 src/ocre/CMakeLists.txt delete mode 100644 src/ocre/api/ocre_api.c delete mode 100644 src/ocre/api/ocre_common.c delete mode 100644 src/ocre/component/component.c delete mode 100644 src/ocre/component/component.h delete mode 100644 src/ocre/components/container_supervisor/component_supervisor.yaml delete mode 100644 src/ocre/components/container_supervisor/cs_main.c delete mode 100644 src/ocre/components/container_supervisor/cs_sm.c delete mode 100644 src/ocre/components/container_supervisor/cs_sm.h delete mode 100644 src/ocre/components/container_supervisor/cs_sm_impl.c delete mode 100644 src/ocre/components/container_supervisor/cs_sm_impl.h delete mode 100644 src/ocre/components/container_supervisor/message_types.h create mode 100644 src/ocre/container.c create mode 100644 src/ocre/container.h create mode 100644 src/ocre/context.c create mode 100644 src/ocre/context.h create mode 100644 src/ocre/include/ocre/ocre.h create mode 100644 src/ocre/include/uthash/utarray.h create mode 100644 src/ocre/include/uthash/uthash.h create mode 100644 src/ocre/include/uthash/utlist.h create mode 100644 src/ocre/include/uthash/utringbuffer.h create mode 100644 src/ocre/include/uthash/utstack.h create mode 100644 src/ocre/include/uthash/utstring.h create mode 100644 src/ocre/ocre.c delete mode 100644 src/ocre/ocre_container_runtime/ocre_container_runtime.c delete mode 100644 src/ocre/ocre_container_runtime/ocre_container_runtime.h delete mode 100644 src/ocre/ocre_messaging/ocre_messaging.c delete mode 100644 src/ocre/ocre_timers/ocre_timer.c delete mode 100644 src/ocre/shell/ocre_shell.c delete mode 100644 src/ocre/shell/ocre_shell.h delete mode 100644 src/ocre/sm/sm.c delete mode 100644 src/ocre/sm/sm.h create mode 100644 src/ocre/unique_random_id.c create mode 100644 src/ocre/unique_random_id.h create mode 100644 src/ocre/util/string_array.c create mode 100644 src/ocre/util/string_array.h delete mode 100644 src/ocre/utils/c-smf/CMakeLists.txt delete mode 100644 src/ocre/utils/c-smf/LICENSE delete mode 100644 src/ocre/utils/c-smf/README.md delete mode 100644 src/ocre/utils/c-smf/smf/CMakeLists.txt delete mode 100644 src/ocre/utils/c-smf/smf/smf.c delete mode 100644 src/ocre/utils/c-smf/smf/smf.h delete mode 100644 src/ocre/utils/c-smf/test/CMakeLists.txt delete mode 100644 src/ocre/utils/c-smf/test/test.c create mode 100644 src/ocre/version.h create mode 100644 src/platform/include/ocre/platform/file.h create mode 100644 src/platform/include/ocre/platform/memory.h create mode 100644 src/platform/posix/CMakeLists.txt create mode 100644 src/platform/posix/file_alloc_fread.c create mode 100644 src/platform/posix/file_alloc_read.c create mode 100644 src/platform/posix/file_mmap.c create mode 100644 src/platform/posix/include/ocre/platform/config.h create mode 100644 src/platform/posix/include/ocre/platform/log.h create mode 100644 src/platform/posix/memory.c create mode 100644 src/platform/zephyr/CMakeLists.txt create mode 100644 src/platform/zephyr/include/ocre/platform/config.h create mode 100644 src/platform/zephyr/include/ocre/platform/log.h create mode 100644 src/platform/zephyr/memory.c create mode 100644 src/runtime/CMakeLists.txt create mode 100644 src/runtime/include/ocre/runtime/vtable.h create mode 100644 src/runtime/wamr/CMakeLists.txt create mode 100644 src/runtime/wamr/include/ocre/runtime/wamr/wamr.h create mode 100644 src/runtime/wamr/ocre_api/CMakeLists.txt create mode 100644 src/runtime/wamr/ocre_api/core/core_eventq.c rename src/{shared/platform/ocre_core_external.h => runtime/wamr/ocre_api/core/core_external.h} (90%) create mode 100644 src/runtime/wamr/ocre_api/core/core_internal.h rename src/{messaging/message_types.h => runtime/wamr/ocre_api/core/core_memory.c} (55%) create mode 100644 src/runtime/wamr/ocre_api/core/core_misc.c create mode 100644 src/runtime/wamr/ocre_api/core/core_mutex.c create mode 100644 src/runtime/wamr/ocre_api/core/core_slist.c create mode 100644 src/runtime/wamr/ocre_api/core/core_timer.c create mode 100644 src/runtime/wamr/ocre_api/ocre_api.c rename src/{ocre/api => runtime/wamr/ocre_api}/ocre_api.h (67%) create mode 100644 src/runtime/wamr/ocre_api/ocre_common.c rename src/{ocre/api => runtime/wamr/ocre_api}/ocre_common.h (59%) rename src/{ocre => runtime/wamr/ocre_api}/ocre_gpio/ocre_gpio.c (99%) rename src/{ocre => runtime/wamr/ocre_api}/ocre_gpio/ocre_gpio.h (100%) create mode 100644 src/runtime/wamr/ocre_api/ocre_messaging/ocre_messaging.c rename src/{ocre => runtime/wamr/ocre_api}/ocre_messaging/ocre_messaging.h (84%) rename src/{ocre => runtime/wamr/ocre_api}/ocre_sensors/custom,rng-sensor.yaml (100%) rename src/{ocre => runtime/wamr/ocre_api}/ocre_sensors/ocre_sensors.c (99%) rename src/{ocre => runtime/wamr/ocre_api}/ocre_sensors/ocre_sensors.h (100%) rename src/{ocre => runtime/wamr/ocre_api}/ocre_sensors/rng_sensor.c (100%) rename src/{ocre => runtime/wamr/ocre_api}/ocre_sensors/rng_sensor.h (100%) rename src/{ocre => runtime/wamr/ocre_api}/ocre_sensors/usage.md (100%) create mode 100644 src/runtime/wamr/ocre_api/ocre_timers/ocre_timer.c rename src/{ocre => runtime/wamr/ocre_api}/ocre_timers/ocre_timer.h (98%) rename src/{ocre => runtime/wamr/ocre_api}/utils/strlcat.c (63%) rename src/{ocre/utils/utils.h => runtime/wamr/ocre_api/utils/strlcat.h} (62%) create mode 100644 src/runtime/wamr/wamr.c delete mode 100644 src/samples-mini/posix/main.c create mode 100644 src/samples/bash_runtime/posix/CMakeLists.txt create mode 100644 src/samples/bash_runtime/posix/bash/CMakeLists.txt create mode 100644 src/samples/bash_runtime/posix/bash/bash.c create mode 100644 src/samples/bash_runtime/posix/bash/include/ocre/runtime/bash/bash.h create mode 100644 src/samples/bash_runtime/posix/main.c create mode 100644 src/samples/demo/main.c create mode 100644 src/samples/demo/posix/CMakeLists.txt create mode 100644 src/samples/demo/zephyr/CMakeLists.txt create mode 100644 src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33_w.conf create mode 100644 src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay create mode 100644 src/samples/demo/zephyr/prj.conf create mode 100644 src/samples/mini/main.c create mode 100644 src/samples/mini/posix/CMakeLists.txt create mode 100644 src/samples/mini/zephyr/CMakeLists.txt create mode 100644 src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33_w.conf create mode 100644 src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay create mode 100644 src/samples/mini/zephyr/prj.conf create mode 100644 src/samples/readline/posix/CMakeLists.txt create mode 100644 src/samples/readline/posix/ocre.c create mode 100644 src/samples/supervisor/zephyr/CMakeLists.txt create mode 100644 src/samples/supervisor/zephyr/boards/b_u585i_iot02a.conf rename {boards => src/samples/supervisor/zephyr/boards}/b_u585i_iot02a.overlay (86%) create mode 100644 src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.conf create mode 100644 src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay create mode 100644 src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w_mcuboot.conf create mode 100644 src/samples/supervisor/zephyr/prj.conf create mode 100644 src/samples/supervisor/zephyr/service.c create mode 100644 src/samples/supervisor/zephyr/shell.c delete mode 100644 src/shared/platform/posix/core_eventq.c delete mode 100644 src/shared/platform/posix/core_fs.c delete mode 100644 src/shared/platform/posix/core_internal.h delete mode 100644 src/shared/platform/posix/core_memory.c delete mode 100644 src/shared/platform/posix/core_misc.c delete mode 100644 src/shared/platform/posix/core_mq.c delete mode 100644 src/shared/platform/posix/core_mutex.c delete mode 100644 src/shared/platform/posix/core_slist.c delete mode 100644 src/shared/platform/posix/core_thread.c delete mode 100644 src/shared/platform/posix/core_timer.c delete mode 100644 src/shared/platform/posix/ocre_internal.cmake delete mode 100644 src/shared/platform/zephyr/core_eventq.c delete mode 100644 src/shared/platform/zephyr/core_fs.c delete mode 100644 src/shared/platform/zephyr/core_internal.h delete mode 100644 src/shared/platform/zephyr/core_memory.c delete mode 100644 src/shared/platform/zephyr/core_misc.c delete mode 100644 src/shared/platform/zephyr/core_mq.c delete mode 100644 src/shared/platform/zephyr/core_mutex.c delete mode 100644 src/shared/platform/zephyr/core_thread.c delete mode 100644 src/shared/platform/zephyr/core_timer.c delete mode 100644 src/shared/platform/zephyr/ocre_internal.cmake create mode 100644 src/shell/CMakeLists.txt create mode 100644 src/shell/command.h create mode 100644 src/shell/container.c create mode 100644 src/shell/container.h create mode 100644 src/shell/container/create.c create mode 100644 src/shell/container/create.h create mode 100644 src/shell/container/inspect.c create mode 100644 src/shell/container/inspect.h create mode 100644 src/shell/container/kill.c create mode 100644 src/shell/container/kill.h create mode 100644 src/shell/container/ps.c create mode 100644 src/shell/container/ps.h create mode 100644 src/shell/container/rm.c create mode 100644 src/shell/container/rm.h create mode 100644 src/shell/container/start.c create mode 100644 src/shell/container/start.h create mode 100644 src/shell/container/stop.c create mode 100644 src/shell/container/stop.h create mode 100644 src/shell/container/wait.c create mode 100644 src/shell/container/wait.h create mode 100644 src/shell/image.c create mode 100644 src/shell/image.h create mode 100644 src/shell/image/ls.c create mode 100644 src/shell/image/ls.h create mode 100644 src/shell/image/pull.c create mode 100644 src/shell/image/pull.h create mode 100644 src/shell/image/rm.c create mode 100644 src/shell/image/rm.h create mode 100644 src/shell/include/ocre/shell/shell.h create mode 100644 src/shell/sha256/LICENSE create mode 100644 src/shell/sha256/sha256.c create mode 100644 src/shell/sha256/sha256.h create mode 100644 src/shell/shell.c delete mode 100644 tools/automsg create mode 100644 zephyr/CMakeLists.txt rename Kconfig => zephyr/Kconfig (52%) create mode 100644 zephyr/user_data.cmake create mode 100644 zephyr/wamr copy.cmake create mode 100644 zephyr/wamr.cmake diff --git a/.clang-format b/.clang-format index 16a28068..49340b0a 100644 --- a/.clang-format +++ b/.clang-format @@ -4,21 +4,22 @@ --- BasedOnStyle: LLVM -AlignConsecutiveMacros: AcrossComments +AlignConsecutiveMacros: AcrossEmptyLinesAndComments AllowShortBlocksOnASingleLine: Never AllowShortCaseLabelsOnASingleLine: false AllowShortEnumsOnASingleLine: false AllowShortFunctionsOnASingleLine: None AllowShortIfStatementsOnASingleLine: false AllowShortLoopsOnASingleLine: false -BitFieldColonSpacing: After -BreakBeforeBraces: Attach +BitFieldColonSpacing: Both +BreakBeforeBraces: Linux ColumnLimit: 120 ConstructorInitializerIndentWidth: 8 ContinuationIndentWidth: 8 -IndentCaseLabels: true -IndentWidth: 4 -InsertBraces: true +IndentCaseLabels: true # Linux is false +IndentWidth: 8 +LineEnding: LF SpaceBeforeParens: ControlStatementsExceptControlMacros -SortIncludes: Never -#UseTab: ForContinuationAndIndentation \ No newline at end of file +SortIncludes: false +UseTab: Always +TabWidth: 8 diff --git a/.clangd b/.clangd new file mode 100644 index 00000000..7721f26c --- /dev/null +++ b/.clangd @@ -0,0 +1,2 @@ +CompileFlags: + CompilationDatabase: build diff --git a/.gitignore b/.gitignore index f1a742d7..44bc6dde 100644 --- a/.gitignore +++ b/.gitignore @@ -61,3 +61,7 @@ Thumbs.db .vscode/ # Generated by VS settings.json + +.cache/ + +src/ocre/commit_id.h diff --git a/.gitmodules b/.gitmodules index 845161b9..dcc009fb 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,3 +2,9 @@ path = wasm-micro-runtime url = https://github.com/project-ocre/wasm-micro-runtime.git branch = staging +[submodule "libwebsockets"] + path = libwebsockets + url = https://libwebsockets.org/repo/libwebsockets +[submodule "ocre-sdk"] + path = ocre-sdk + url = git@github.com:project-ocre/ocre-sdk.git diff --git a/.vscode/launch.json b/.vscode/launch.json index 540ecc9f..27dd2bd9 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,19 +1,16 @@ { + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { - "name": "Cortex Debug - ST-LINK", + "name": "C++ Launch", + "type": "cppdbg", "request": "launch", - "cwd": "${workspaceFolder}", - "executable": "${workspaceFolder}/zephyr/build/zephyr/zephyr.elf", - "runToEntryPoint": "main", - "showDevDebugOutput": "none", - "type": "cortex-debug", - "servertype": "stlink", - "stm32cubeprogrammer": "", - "interface": "swd", - "device": "STM32U5xx", - "v1": false + "program": "${workspaceFolder}/build/src/samples/bash_runtime/posix/ocre_bash", + "cwd": "${workspaceFolder}/build", + "MIMode": "lldb" } ] } \ No newline at end of file diff --git a/.zed/debug.json b/.zed/debug.json new file mode 100644 index 00000000..f231e8f6 --- /dev/null +++ b/.zed/debug.json @@ -0,0 +1,22 @@ +// Project-local debug tasks +// +// For more documentation on how to configure debug tasks, +// see: https://zed.dev/docs/debugger + +[ + { + "adapter": "CodeLLDB", + "label": "Debug ", + "request": "launch", + // "program": "build/src/samples/bash_runtime/posix/ocre_bash", + // "program": "build/src/samples/mini/posix/ocre_mini", + "program": "build/src/samples/supervisor/posix/ocre", + "args": ["container", "ps"], + "cwd": "$ZED_WORKTREE_ROOT/build" + // "build": { + // "command": "make", + // // "args": ["build", "-j8"], + // "cwd": "$ZED_WORKTREE_ROOT/build" + // } + } +] diff --git a/.zed/tasks.json b/.zed/tasks.json new file mode 100644 index 00000000..99a563a0 --- /dev/null +++ b/.zed/tasks.json @@ -0,0 +1,16 @@ +[ + { + "label": "DevContainer: Up", + "command": "devcontainer up - workspace-folder ${ZED_WORKTREE_ROOT}", + "use_new_terminal": true, + "allow_concurrent_runs": false, + "reveal": "always" + }, + { + "label": "DevContainer: Build", + "command": "devcontainer build - workspace-folder ${ZED_WORKTREE_ROOT}", + "use_new_terminal": true, + "allow_concurrent_runs": false, + "reveal": "always" + } +] diff --git a/CMakeLists.txt b/CMakeLists.txt index 38367542..fa3ac6aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,82 +1,38 @@ cmake_minimum_required(VERSION 3.20.0) -# Allow user to set CMAKE_SYSTEM_NAME via -DCMAKE_SYSTEM_NAME=Zephyr or Linux -if(NOT DEFINED TARGET_PLATFORM_NAME) - set(TARGET_PLATFORM_NAME "Zephyr") -endif() +project(ocre LANGUAGES C ASM) -if(TARGET_PLATFORM_NAME STREQUAL "Linux") - project(ocre LANGUAGES C ASM) -elseif(TARGET_PLATFORM_NAME STREQUAL "Zephyr") - find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) - project(ocre VERSION ${APP_VERSION_MAJOR}.${APP_VERSION_MINOR}.${APP_PATCHLEVEL}.${APP_VERSION_TWEAK} LANGUAGES C ASM) -else() - message(FATAL_ERROR "Unsupported TARGET_PLATFORM_NAME: ${TARGET_PLATFORM_NAME}") -endif() +set(CMAKE_BUILD_TYPE Debug) +set(CMAKE_C_FLAGS "-Wall") -# ----------- COMMON SECTION ----------- set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set(CMAKE_VERBOSE_MAKEFILE ON) + set(CMAKE_C_STANDARD 99) set(CMAKE_CXX_STANDARD 17) -# Version and build info (common) -execute_process( - COMMAND git describe --long --dirty --always - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_VARIABLE RAW_GIT_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE -) -string(REPLACE "-dirty" "+" BUILD_INFO ${RAW_GIT_VERSION}) -string(TIMESTAMP BUILD_DATE "%d-%m-%Y, %H:%M" UTC ) -cmake_host_system_information(RESULT BUILD_MACHINE QUERY HOSTNAME) -string(PREPEND BUILD_INFO dev-) -string(REPLACE "-" ";" GIT_INFO_LIST ${RAW_GIT_VERSION}) -list(GET GIT_INFO_LIST 0 VERSION_NUMBER) - -# Message generation (common) -set(OCRE_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}) -set(MSG_INPUT_FILES ${OCRE_ROOT_DIR}/src/ocre/components/container_supervisor/component_supervisor.yaml ) -set(MSG_GENERATED_FILE ${CMAKE_CURRENT_LIST_DIR}/src/messaging/messages.g) +set(WAMR_BUILD_PLATFORM linux) +# set(WAMR_BUILD_PLATFORM darwin) -# Zephyr toolchain usually provides PYTHON_EXECUTABLE -if(NOT DEFINED PYTHON_EXECUTABLE) - find_package(Python3 QUIET REQUIRED Interpreter Development) - if(NOT Python3_FOUND) - message(FATAL_ERROR "Python3 interpreter not found. Please install Python3 or set PYTHON_EXECUTABLE to the path of your Python interpreter.") - endif() - set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE}) -endif() +# /var/lib/ocre directory +include (cmake/state_information.cmake) -add_custom_command( - OUTPUT ${MSG_GENERATED_FILE} - COMMAND ${PYTHON_EXECUTABLE} ${OCRE_ROOT_DIR}/tools/automsg ${MSG_INPUT_FILES} ${MSG_GENERATED_FILE} - DEPENDS ${MSG_INPUT_FILES} - COMMENT "Running Python script to generate ${MSG_GENERATED_FILE}" -) -add_custom_target(generate_messages DEPENDS ${MSG_GENERATED_FILE}) +# core +add_subdirectory(src/ocre) +add_subdirectory(src/runtime) -if(NOT "${OCRE_INPUT_FILE}" STREQUAL "") - message("Using input file: ${OCRE_INPUT_FILE}") - - # Extract filename without extension for use in software - get_filename_component(OCRE_INPUT_FILE_NAME ${OCRE_INPUT_FILE} NAME_WE) - message("Input file name (without extension): ${OCRE_INPUT_FILE_NAME}") - add_definitions(-DOCRE_INPUT_FILE_NAME="${OCRE_INPUT_FILE_NAME}") - - add_custom_command( - OUTPUT ${CMAKE_CURRENT_LIST_DIR}/src/ocre/ocre_input_file.g - COMMAND xxd -i ${OCRE_INPUT_FILE} | sed 's/unsigned char .*\\[/static const unsigned char wasm_binary[/' | sed 's/unsigned int .*_len/static const unsigned int wasm_binary_len/' > ${CMAKE_CURRENT_LIST_DIR}/src/ocre/ocre_input_file.g - DEPENDS ${OCRE_INPUT_FILE} - COMMENT "Generating C header from ${OCRE_INPUT_FILE}" - ) +# runtime +include (cmake/wamr.cmake) +add_subdirectory(src/runtime/wamr) - add_definitions(-DHAS_GENERATED_INPUT) +# platform +add_subdirectory(src/platform/posix) - add_custom_target(generate_ocre_file DEPENDS ${CMAKE_CURRENT_LIST_DIR}/src/ocre/ocre_input_file.g) -endif() +# shell +add_subdirectory(src/shell) -if(TARGET_PLATFORM_NAME STREQUAL "Linux") - include(${CMAKE_CURRENT_LIST_DIR}/src/shared/platform/posix/ocre_internal.cmake) -elseif(TARGET_PLATFORM_NAME STREQUAL "Zephyr") - include(${CMAKE_CURRENT_LIST_DIR}/src/shared/platform/zephyr/ocre_internal.cmake) -endif() +# samples +add_subdirectory(src/samples/mini/posix) +add_subdirectory(src/samples/demo/posix) +add_subdirectory(src/samples/supervisor/posix) +add_subdirectory(src/samples/bash_runtime/posix) diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..0a73d2b8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,79 @@ +FROM ubuntu:22.04 + +# for apt to be noninteractive +ENV DEBIAN_FRONTEND=noninteractive +ENV DEBCONF_NONINTERACTIVE_SEEN=true + +RUN truncate -s0 /tmp/preseed.cfg; \ + echo "tzdata tzdata/Areas select Europe" >> /tmp/preseed.cfg; \ + echo "tzdata tzdata/Zones/Europe select Madrid" >> /tmp/preseed.cfg; \ + debconf-set-selections /tmp/preseed.cfg && \ + rm -f /etc/timezone /etc/localtime + +RUN apt-get -q update && apt-get install --no-install-recommends -y\ + build-essential\ + ccache\ + cmake\ + device-tree-compiler\ + dfu-util\ + file\ + gcc\ + g++\ + git\ + gperf\ + libmagic1\ + locales\ + make\ + ninja-build\ + openssh-server\ + python3\ + python3-dev\ + python3-venv\ + sudo\ + supervisor\ + tzdata\ + wget\ + xz-utils + +RUN /usr/sbin/locale-gen en_US.UTF-8 +ENV LANG=en_US.UTF-8 + +RUN mkdir -p /var/run/sshd /var/log/supervisor + +#COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf + +RUN cat << EOF > /etc/supervisor/conf.d/supervisord.conf +[supervisord] +nodaemon=true +user=root + +[program:sshd] +command=/usr/sbin/sshd -D +autostart=true +autorestart=true +EOF + +EXPOSE 22 +CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"] + +# create users +RUN echo "[color]\n\tui = false\n[user]\n\tname = Marco\n\temail = marco.casaroli@gmail.com" > /etc/skel/.gitconfig + +ARG USER_NAME=marco + +# ===== create user/setup environment ===== +# this is for ubuntu user (uid=1000, gid=1000) +RUN useradd --create-home --shell /bin/bash --groups sudo ${USER_NAME} +RUN echo "${USER_NAME} ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/${USER_NAME} + +RUN \ + mkdir -p /home/${USER_NAME}/.ssh/ &&\ + echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHOQDCuzFBPW2VeYBGhcmJgoecMM99Uea/C4gExUqZPn marco@Marcos-Silver-MacBook-Pro.local" > /home/${USER_NAME}/.ssh/authorized_keys &&\ + chown -R ${USER_NAME}:${USER_NAME} /home/${USER_NAME}/.ssh + +# use bash as shell +SHELL ["/bin/bash", "-c"] + +# working directory +#USER ${USER_NAME} +#WORKDIR /home/${USER_NAME} diff --git a/TODO.txt b/TODO.txt new file mode 100644 index 00000000..0d7c5e2d --- /dev/null +++ b/TODO.txt @@ -0,0 +1,40 @@ +# TODO MVP + +- version DONE +- sample container DONE +- detached create DONE +- envp argv handle copy in ocre not runtime DONE +- capabilities DONE +- shared heap DONE +- supervisor shell integration in zephyr DONE +- zephyr littlefs integration user partition DONE +- ocre api + - timer DONE + - messaging DONE + - gpio + - sensor +- timer cleanup +- dir mounts +- http client +- shell container stop +- shell image pull +- shell container inspect +- shell container wait +- documentation +- fix hack for commit id and build info +- CONFIG_THREAD_RUNTIME_STATS # needed by the latest version of WARM for time APIs +- IPC / remote context +- log level posix +- log integration review + +- wamr stop +- pause/resume +- SHELL pause/unpause +- tests +- https client +- io redirection +- ocre attach +- ocre volume +- wamr zephyr build +- SHELL stop +- SHELL status diff --git a/boards/b_u585i_iot02a.conf b/boards/b_u585i_iot02a.conf deleted file mode 100644 index 6efe69b4..00000000 --- a/boards/b_u585i_iot02a.conf +++ /dev/null @@ -1,57 +0,0 @@ -# Memory configuration and sizes -CONFIG_ARM_MPU=y -CONFIG_MAIN_STACK_SIZE=8192 -CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=-1 - -# PSRAM -CONFIG_MEMC=y - -# Container defaults -CONFIG_MAX_CONTAINERS=5 - -# Bus interfaces -CONFIG_GPIO=y -CONFIG_I2C=y -CONFIG_SPI=y - -# W5500 Ethernet driver -CONFIG_ETH_W5500=y -CONFIG_NET_L2_ETHERNET=y - -# Ocre Sensors support -CONFIG_SENSOR=y -CONFIG_OCRE_SENSORS=y -CONFIG_RNG_SENSOR=y - -CONFIG_SENSOR_SHELL=y -CONFIG_SENSOR_INFO=y - -# Onboard sensors -CONFIG_ISM330DHCX=y -CONFIG_LPS22HH=y -CONFIG_HTS221=y -CONFIG_IIS2MDC=y -CONFIG_VEML7700=y - -# Ocre options -CONFIG_OCRE_CONTAINER_FILESYSTEM=y - -# Ocre GPIO Support -CONFIG_OCRE_GPIO=y -CONFIG_OCRE_GPIO_MAX_PORTS=8 -CONFIG_OCRE_GPIO_PINS_PER_PORT=16 -CONFIG_OCRE_GPIO_MAX_PINS=256 - -CONFIG_CODE_DATA_RELOCATION=n - -# Networking options -CONFIG_NET_TCP=y -CONFIG_NET_MAX_CONN=10 - -# Zephyr Virtual File System (ZVFS) options. Needed for container filesystem and sockets -CONFIG_ZVFS_OPEN_MAX=15 -CONFIG_ZVFS_EVENTFD_MAX=10 -CONFIG_NET_SOCKETS_POLL_MAX=10 - -# Enable container networking support -CONFIG_OCRE_NETWORKING=y diff --git a/boards/enc28j60.conf b/boards/enc28j60.conf deleted file mode 100644 index f6a8f028..00000000 --- a/boards/enc28j60.conf +++ /dev/null @@ -1,3 +0,0 @@ -# ENC28J60 Ethernet driver -CONFIG_ETH_ENC28J60=y -CONFIG_ETH_W5500=n diff --git a/boards/enc28j60.overlay b/boards/enc28j60.overlay deleted file mode 100644 index 93d9d757..00000000 --- a/boards/enc28j60.overlay +++ /dev/null @@ -1,11 +0,0 @@ -&spi1 { - eth0: ethernet@0 { - status = "okay"; - reg = <0>; - compatible = "microchip,enc28j60"; - int-gpios = <&gpioc 1 GPIO_ACTIVE_LOW>; - spi-max-frequency = <10000000>; - local-mac-address = [ 00 80 00 01 02 03 ]; - full-duplex; - }; -}; diff --git a/boards/native_sim.conf b/boards/native_sim.conf deleted file mode 100644 index 32f34508..00000000 --- a/boards/native_sim.conf +++ /dev/null @@ -1,35 +0,0 @@ -CONFIG_UART_NATIVE_PTY_0_ON_STDINOUT=y -CONFIG_UART_NATIVE_PTY=y -CONFIG_FLASH_SIMULATOR=y -CONFIG_ENTROPY_GENERATOR=y -CONFIG_TEST_RANDOM_GENERATOR=y - -CONFIG_MPU_ALLOW_FLASH_WRITE=y - -CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME=y - -# Support for NET_OFFLOAD adapter -CONFIG_ETH_NATIVE_POSIX=n -CONFIG_NET_DRIVERS=y -CONFIG_NET_SOCKETS_OFFLOAD=y -CONFIG_NET_NATIVE_OFFLOADED_SOCKETS=y - -# The NET_OFFLOAD adapter requires setting an IP address to satisfy the Zephyr networking stack -# This address is not actually used, but it must be set to a valid value. The underlying host's -# networking address will be used to communicate with the network. -CONFIG_NET_CONFIG_SETTINGS=y -CONFIG_NET_CONFIG_MY_IPV4_ADDR="127.0.0.1" -CONFIG_NET_CONFIG_MY_IPV4_GW="127.0.0.1" -CONFIG_NET_CONFIG_MY_IPV4_NETMASK="255.255.255.0" - -CONFIG_NET_DHCPV4=n - -# Suppress logging from FS and LittleFS -CONFIG_FS_LOG_LEVEL_OFF=y - -# This is required to work around an issue where "-1" causes a crash using the `native_sim` -CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=262144 -CONFIG_GPIO=y - -# Ocre options -CONFIG_OCRE_CONTAINER_FILESYSTEM=y diff --git a/boards/native_sim.overlay b/boards/native_sim.overlay deleted file mode 100644 index 8bf90af4..00000000 --- a/boards/native_sim.overlay +++ /dev/null @@ -1,39 +0,0 @@ -/ { - chosen { - zephyr,console = &uart0; - zephyr,shell-uart = &uart0; - zephyr,uart-mcumgr = &uart0; - }; - - aliases { - rng0 = &rng_device; - }; - - devices{ - rng_device: rng_0 { - compatible = "custom,rng-sensor"; - label = "RNG Sensor"; - status = "okay"; - }; - }; -}; - -/delete-node/ &storage_partition; -/delete-node/ &scratch_partition; - -&flash0 { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - user_data_partition: partition@de000 { - label = "user-data"; - reg = <0x000de000 0x0001e000>; - }; - storage_partition: partition@100000 { - label = "storage"; - reg = <0x100000 0x00004000>; - }; - }; -}; diff --git a/cmake/input_file.cmake b/cmake/input_file.cmake new file mode 100644 index 00000000..2cd9fdd6 --- /dev/null +++ b/cmake/input_file.cmake @@ -0,0 +1,19 @@ +if(NOT "${OCRE_INPUT_FILE}" STREQUAL "") + message("Using input file: ${OCRE_INPUT_FILE}") + + # Extract filename without extension for use in software + get_filename_component(OCRE_INPUT_FILE_NAME ${OCRE_INPUT_FILE} NAME_WE) + message("Input file name (without extension): ${OCRE_INPUT_FILE_NAME}") + add_definitions(-DOCRE_INPUT_FILE_NAME="${OCRE_INPUT_FILE_NAME}") + + add_custom_command( + OUTPUT ${CMAKE_CURRENT_LIST_DIR}/src/ocre/ocre_input_file.g + COMMAND xxd -n wasm_binary -i ${OCRE_INPUT_FILE} | sed 's/^unsigned/static const unsigned/' > ${OCRE_ROOT_DIR}/src/ocre/ocre_input_file.g + DEPENDS ${OCRE_INPUT_FILE} + COMMENT "Generating C header from ${OCRE_INPUT_FILE}" + ) + + add_definitions(-DHAS_GENERATED_INPUT) + + add_custom_target(generate_ocre_file DEPENDS ${CMAKE_CURRENT_LIST_DIR}/src/ocre/ocre_input_file.g) +endif() diff --git a/cmake/state_information.cmake b/cmake/state_information.cmake new file mode 100644 index 00000000..e6d2974c --- /dev/null +++ b/cmake/state_information.cmake @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.20.0) + +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/var/lib/ocre/images) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/var/lib/ocre/volumes) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/var/lib/ocre/containers) + +if (OCRE_INPUT_FILE_NAME) + message(DEPRECATION "Adding '${OCRE_INPUT_FILE_NAME}' to preloaded images. Please use OCRE_PRELOADED_IMAGES instead.") + list(APPEND OCRE_PRELOADED_IMAGES ${OCRE_INPUT_FILE_NAME}) +endif() + +foreach(image IN ITEMS ${OCRE_PRELOADED_IMAGES}) + message(STATUS "Adding '${image}' to preloaded images") + file(COPY ${image} DESTINATION var/lib/ocre/images/) + cmake_path(GET image FILENAME filename) + list(APPEND OCRE_IMAGES ${CMAKE_CURRENT_BINARY_DIR}/var/lib/ocre/images/${filename}) +endforeach() diff --git a/cmake/wamr.cmake b/cmake/wamr.cmake new file mode 100644 index 00000000..2f3d99e1 --- /dev/null +++ b/cmake/wamr.cmake @@ -0,0 +1,46 @@ +set (WAMR_BUILD_INTERP 1) +set (WAMR_BUILD_FAST_INTERP 0) +set (WAMR_BUILD_AOT 0) +set (WAMR_BUILD_JIT 0) +set (WAMR_BUILD_LIBC_BUILTIN 0) +set (WAMR_BUILD_LIBC_WASI 1) +set (WAMR_BUILD_LIB_PTHREAD 1) +set (WAMR_BUILD_REF_TYPES 1) +set (WASM_ENABLE_LOG 1) +set (WAMR_BUILD_SHARED_HEAP 1) + +if (NOT DEFINED WAMR_BUILD_PLATFORM) + set (WAMR_BUILD_PLATFORM "linux") +endif() + +if (NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_POOL) + set (WAMR_BUILD_GLOBAL_HEAP_POOL 1) +endif () +if (NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_SIZE) + set (WAMR_BUILD_GLOBAL_HEAP_SIZE 32767) +endif () + +# Set WAMR_BUILD_TARGET, currently values supported: +# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", +# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]" +if (NOT DEFINED WAMR_BUILD_TARGET) + if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)") + set (WAMR_BUILD_TARGET "AARCH64") + if (NOT DEFINED WAMR_BUILD_SIMD) + set (WAMR_BUILD_SIMD 1) + endif () + elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") + set (WAMR_BUILD_TARGET "RISCV64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) + set (WAMR_BUILD_TARGET "X86_64") + if (NOT DEFINED WAMR_BUILD_SIMD) + set (WAMR_BUILD_SIMD 1) + endif () + elseif (CMAKE_SIZEOF_VOID_P EQUAL 4) + set (WAMR_BUILD_TARGET "X86_32") + else () + message(SEND_ERROR "Unsupported build target platform!") + endif () +endif () + +add_subdirectory(wasm-micro-runtime) diff --git a/modules/modules.cmake b/modules/modules.cmake deleted file mode 100644 index af2c7429..00000000 --- a/modules/modules.cmake +++ /dev/null @@ -1 +0,0 @@ -# This project uses .gitmodules to manage various modules due to cross-platform solutions diff --git a/prj.conf b/prj.conf deleted file mode 100644 index 51e4fe66..00000000 --- a/prj.conf +++ /dev/null @@ -1,89 +0,0 @@ -CONFIG_SHELL=y -CONFIG_BOOT_BANNER=y -CONFIG_SHELL_PROMPT_UART="ocre:~$ " -CONFIG_NET_SHELL=y -CONFIG_HWINFO=y -CONFIG_NET_L2_WIFI_SHELL=n -CONFIG_FILE_SYSTEM_SHELL=y - -CONFIG_DEBUG=n -CONFIG_DEBUG_OPTIMIZATIONS=y -CONFIG_DEBUG_THREAD_INFO=y - -CONFIG_LOG=y -CONFIG_LOG_MODE_MINIMAL=y -CONFIG_ZCBOR_VERBOSE=n - -CONFIG_THREAD_RUNTIME_STATS=y # Needed by the latest version of WARM for time APIs - -# Allow for dynamically created threads -CONFIG_DYNAMIC_THREAD=y -CONFIG_DYNAMIC_THREAD_ALLOC=y - -# File system -CONFIG_FILE_SYSTEM=y -#CONFIG_DISK_ACCESS=y -CONFIG_FILE_SYSTEM_LITTLEFS=y - -# Settings support -CONFIG_SETTINGS=y -CONFIG_SETTINGS_FILE=y -CONFIG_SETTINGS_FILE_PATH="/lfs/settings" - -# Networking options -CONFIG_NET_IPV4=y -CONFIG_NET_IPV6=n -CONFIG_NET_UDP=y -CONFIG_NET_SOCKETS=y - -CONFIG_NET_TX_STACK_SIZE=2048 -CONFIG_NET_BUF_TX_COUNT=16 -CONFIG_NET_RX_STACK_SIZE=4096 -CONFIG_NET_BUF_RX_COUNT=32 -CONFIG_NET_MGMT_EVENT_STACK_SIZE=2048 -CONFIG_ZVFS_POLL_MAX=5 - -CONFIG_NET_DHCPV4=y - -# MCU Boot options -CONFIG_BOOTLOADER_MCUBOOT=n -CONFIG_IMG_MANAGER=y -CONFIG_MCUBOOT_IMG_MANAGER=y -CONFIG_STREAM_FLASH=y -CONFIG_IMG_ERASE_PROGRESSIVELY=y - -# System API options -CONFIG_POSIX_API=y - -# Memory / malloc optopns -CONFIG_HEAP_MEM_POOL_SIZE=65536 -CONFIG_MAIN_STACK_SIZE=8192 -CONFIG_SHELL_STACK_SIZE=8192 -CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=8192 -CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=-1 - - -# Ocre configuration -CONFIG_OCRE_CONTAINER_DEFAULT_HEAP_SIZE=4096 -CONFIG_OCRE_CONTAINER_DEFAULT_STACK_SIZE=4096 -CONFIG_LOG_TRACE_SHORT_TIMESTAMP=y - -# Ocre Feature Options -CONFIG_SENSOR=y -CONFIG_RNG_SENSOR=y - -CONFIG_OCRE_CONTAINER_MESSAGING=y -CONFIG_MESSAGING_MAX_SUBSCRIPTIONS=10 - -CONFIG_DEVICE_DT_METADATA=y -CONFIG_DEVICE_DEPS=y - - -CONFIG_MAX_TIMERS=5 -CONFIG_MAX_SENSORS=10 -CONFIG_MAX_CHANNELS_PER_SENSOR=8 - -CONFIG_OCRE_MEMORY_CHECK_ENABLED=n -CONFIG_OCRE_GPIO=y - -CONFIG_OCRE_LOG_INF=y diff --git a/src/ocre/CMakeLists.txt b/src/ocre/CMakeLists.txt new file mode 100644 index 00000000..455ff2b6 --- /dev/null +++ b/src/ocre/CMakeLists.txt @@ -0,0 +1,65 @@ +# Check if we are in a git repository +execute_process( + COMMAND git rev-parse --git-dir + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE GIT_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET +) + +if(GIT_DIR) + message(STATUS "Detected git repository. Automatic commit ID tracking is enabled.") + + # Generate commit ID header file in source dir if we are in a git repository + add_custom_command( + OUTPUT commit_id.h + COMMAND sh -c "echo '/* Auto-generated file. DO NOT EDIT */' > commit_id.h" + COMMAND sh -c "echo \"#define GIT_COMMIT_ID \\\"$(git describe --always --abbrev=0 --dirty)\\\"\" >> commit_id.h" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + VERBATIM + DEPENDS always_rebuild + ) +endif() + +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/ocre) + +# Generate build info header file in binary dir for every build +add_custom_command( + OUTPUT include/ocre/build_info.h + COMMAND sh -c "echo \"#define OCRE_BUILD_HOST_INFO \\\"$ENV{USER} @ $(uname -a) - $(date +'%Y-%m-%d %H:%M:%S %Z')\\\"\"" > include/ocre/build_info.h + VERBATIM + DEPENDS always_rebuild +) + +# dummy command used to make the custom commands be re-run on every build (not just configure) +add_custom_command( + OUTPUT always_rebuild + COMMAND cmake -E echo +) + +add_library(OcreCore) + +# if we are not in a git repository, just fail automatically if we are missing commit_id.h +target_sources(OcreCore + PRIVATE + container.c + context.c + unique_random_id.c + ocre.c + util/string_array.c + commit_id.h + include/ocre/build_info.h +) + +target_link_libraries(OcreCore PUBLIC + OcrePlatform + OcreRuntime + OcreRuntimeWamr +) + +target_include_directories(OcreCore + PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}/include + PUBLIC + include +) diff --git a/src/ocre/api/ocre_api.c b/src/ocre/api/ocre_api.c deleted file mode 100644 index b6aa95de..00000000 --- a/src/ocre/api/ocre_api.c +++ /dev/null @@ -1,152 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - -#include -#include -#include -#include - -#include "ocre_core_external.h" - -#include "bh_platform.h" - -#include "ocre_api.h" - -#ifdef CONFIG_OCRE_TIMER -#include "../ocre_timers/ocre_timer.h" -#endif - -#include "ocre/utils/utils.h" - -#if defined(CONFIG_OCRE_TIMER) || defined(CONFIG_OCRE_GPIO) || defined(CONFIG_OCRE_SENSORS) || defined(CONFIG_OCRE_CONTAINER_MESSAGING) -#include "ocre_common.h" -#endif - -#ifdef CONFIG_OCRE_SENSORS -#include "../ocre_sensors/ocre_sensors.h" -#endif - -#ifdef CONFIG_OCRE_GPIO -#include "../ocre_gpio/ocre_gpio.h" -#endif - -#ifdef CONFIG_OCRE_CONTAINER_MESSAGING -#include "../ocre_messaging/ocre_messaging.h" -#endif - -int _ocre_posix_uname(wasm_exec_env_t exec_env, struct _ocre_posix_utsname *name) { - wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); - if (!module_inst) { - return -1; - } - if (!wasm_runtime_validate_native_addr(module_inst, name, sizeof(struct _ocre_posix_utsname))) { - return -1; - } - - struct utsname info; - if (uname(&info) != 0) { - return -1; - } - - memset(name, 0, sizeof(struct _ocre_posix_utsname)); - - snprintf(name->sysname, OCRE_API_POSIX_BUF_SIZE, "%s (%s)", OCRE_SYSTEM_NAME, info.sysname); - snprintf(name->release, OCRE_API_POSIX_BUF_SIZE, "%s (%s)", APP_VERSION_STRING, info.release); - snprintf(name->version, OCRE_API_POSIX_BUF_SIZE, "%s", info.version); - -#ifdef CONFIG_ARM -#ifdef CONFIG_CPU_CORTEX_M0 - strlcat(name->machine, "ARM Cortex-M0", OCRE_API_POSIX_BUF_SIZE); -#elif CONFIG_CPU_CORTEX_M3 - strlcat(name->machine, "ARM Cortex-M3", OCRE_API_POSIX_BUF_SIZE); -#elif CONFIG_CPU_CORTEX_M4 - strlcat(name->machine, "ARM Cortex-M4", OCRE_API_POSIX_BUF_SIZE); -#elif CONFIG_CPU_CORTEX_M7 - strlcat(name->machine, "ARM Cortex-M7", OCRE_API_POSIX_BUF_SIZE); -#elif CONFIG_CPU_CORTEX_M33 - strlcat(name->machine, "ARM Cortex-M33", OCRE_API_POSIX_BUF_SIZE); -#elif CONFIG_CPU_CORTEX_M23 - strlcat(name->machine, "ARM Cortex-M23", OCRE_API_POSIX_BUF_SIZE); -#elif CONFIG_CPU_CORTEX_M55 - strlcat(name->machine, "ARM Cortex-M55", OCRE_API_POSIX_BUF_SIZE); -#endif -#else - strlcat(name->machine, info.machine, OCRE_API_POSIX_BUF_SIZE); -#endif - - strlcat(name->nodename, info.nodename, OCRE_API_POSIX_BUF_SIZE); - - return 0; -} - -int ocre_sleep(wasm_exec_env_t exec_env, int milliseconds) { - core_sleep_ms(milliseconds); - return 0; -} - -// Ocre Runtime API -NativeSymbol ocre_api_table[] = { - {"uname", _ocre_posix_uname, "(*)i", NULL}, - {"ocre_sleep", ocre_sleep, "(i)i", NULL}, -#if defined(CONFIG_OCRE_TIMER) || defined(CONFIG_OCRE_GPIO) || defined(CONFIG_OCRE_SENSORS) || defined(CONFIG_OCRE_CONTAINER_MESSAGING) - {"ocre_get_event", ocre_get_event, "(iiiiii)i", NULL}, - {"ocre_register_dispatcher", ocre_register_dispatcher, "(i$)i", NULL}, -#endif -// Container Messaging API -#ifdef CONFIG_OCRE_CONTAINER_MESSAGING - {"ocre_publish_message", ocre_messaging_publish, "(***i)i", NULL}, - {"ocre_subscribe_message", ocre_messaging_subscribe, "(*)i", NULL}, - {"ocre_messaging_free_module_event_data", ocre_messaging_free_module_event_data, "(iii)i", NULL}, -#endif -// Sensor API -#ifdef CONFIG_OCRE_SENSORS - {"ocre_sensors_init", ocre_sensors_init, "()i", NULL}, - {"ocre_sensors_discover", ocre_sensors_discover, "()i", NULL}, - {"ocre_sensors_open", ocre_sensors_open, "(i)i", NULL}, - {"ocre_sensors_get_handle", ocre_sensors_get_handle, "(i)i", NULL}, - {"ocre_sensors_get_channel_count", ocre_sensors_get_channel_count, "(i)i", NULL}, - {"ocre_sensors_get_channel_type", ocre_sensors_get_channel_type, "(ii)i", NULL}, - {"ocre_sensors_read", ocre_sensors_read, "(ii)F", NULL}, - {"ocre_sensors_open_by_name", ocre_sensors_open_by_name, "($)i", NULL}, - {"ocre_sensors_get_handle_by_name", ocre_sensors_get_handle_by_name, "($)i", NULL}, - {"ocre_sensors_get_channel_count_by_name", ocre_sensors_get_channel_count_by_name, "($)i", NULL}, - {"ocre_sensors_get_channel_type_by_name", ocre_sensors_get_channel_type_by_name, "($i)i", NULL}, - {"ocre_sensors_read_by_name", ocre_sensors_read_by_name, "($i)F", NULL}, - {"ocre_sensors_get_list", ocre_sensors_get_list, "($i)i", NULL}, -#endif -// Timer API -#ifdef CONFIG_OCRE_TIMER - {"ocre_timer_create", ocre_timer_create, "(i)i", NULL}, - {"ocre_timer_start", ocre_timer_start, "(iii)i", NULL}, - {"ocre_timer_stop", ocre_timer_stop, "(i)i", NULL}, - {"ocre_timer_delete", ocre_timer_delete, "(i)i", NULL}, - {"ocre_timer_get_remaining", ocre_timer_get_remaining, "(i)i", NULL}, -#endif -// GPIO API -#ifdef CONFIG_OCRE_GPIO - {"ocre_gpio_init", ocre_gpio_wasm_init, "()i", NULL}, - {"ocre_gpio_configure", ocre_gpio_wasm_configure, "(iii)i", NULL}, - {"ocre_gpio_pin_set", ocre_gpio_wasm_set, "(iii)i", NULL}, - {"ocre_gpio_pin_get", ocre_gpio_wasm_get, "(ii)i", NULL}, - {"ocre_gpio_pin_toggle", ocre_gpio_wasm_toggle, "(ii)i", NULL}, - {"ocre_gpio_register_callback", ocre_gpio_wasm_register_callback, "(ii)i", NULL}, - {"ocre_gpio_unregister_callback", ocre_gpio_wasm_unregister_callback, "(ii)i", NULL}, - - {"ocre_gpio_configure_by_name", ocre_gpio_wasm_configure_by_name, "($i)i", NULL}, - {"ocre_gpio_set_by_name", ocre_gpio_wasm_set_by_name, "($i)i", NULL}, - {"ocre_gpio_get_by_name", ocre_gpio_wasm_get_by_name, "($)i", NULL}, - {"ocre_gpio_toggle_by_name", ocre_gpio_wasm_toggle_by_name, "($)i", NULL}, - {"ocre_gpio_register_callback_by_name", ocre_gpio_wasm_register_callback_by_name, "($)i", NULL}, - {"ocre_gpio_unregister_callback_by_name", ocre_gpio_wasm_unregister_callback_by_name, "($)i", NULL}, -#endif -}; - -int ocre_api_table_size = sizeof(ocre_api_table) / sizeof(NativeSymbol); diff --git a/src/ocre/api/ocre_common.c b/src/ocre/api/ocre_common.c deleted file mode 100644 index f8362fdd..00000000 --- a/src/ocre/api/ocre_common.c +++ /dev/null @@ -1,389 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre, a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include "ocre_core_external.h" -#include -#include -#include -#include -#include -#include - -LOG_MODULE_DECLARE(ocre_cs_component, OCRE_LOG_LEVEL); - -#ifdef CONFIG_OCRE_GPIO -#include "../ocre_gpio/ocre_gpio.h" -#endif - -#ifdef CONFIG_OCRE_CONTAINER_MESSAGING -#include "../ocre_messaging/ocre_messaging.h" -#endif - -#include "ocre_common.h" - -typedef struct module_node { - ocre_module_context_t ctx; - core_snode_t node; -} module_node_t; - -static core_slist_t module_registry; -static core_mutex_t registry_mutex; - -#define SIZE_OCRE_EVENT_BUFFER 32 - -/* Unified event queue implementation */ -core_eventq_t ocre_event_queue; -bool ocre_event_queue_initialized = false; -core_spinlock_t ocre_event_queue_lock; - -static struct cleanup_handler { - ocre_resource_type_t type; - ocre_cleanup_handler_t handler; -} cleanup_handlers[OCRE_RESOURCE_TYPE_COUNT]; - -bool common_initialized = false; - -/* Thread-Local Storage */ -__thread wasm_module_inst_t *current_module_tls = NULL; - -#if EVENT_THREAD_POOL_SIZE > 0 -// Arguments for event threads -struct event_thread_args { - int index; // Thread index for identification or logging -}; -static struct core_thread event_threads[EVENT_THREAD_POOL_SIZE]; -// Flag to signal event threads to exit gracefully -static volatile bool event_threads_exit = false; -static struct event_thread_args event_args[EVENT_THREAD_POOL_SIZE]; - -// Event thread function to process events from the ring buffer -static void event_thread_fn(void *arg1) { - struct event_thread_args *args = (struct event_thread_args *)arg1; - // Initialize WASM runtime thread environment - wasm_runtime_init_thread_env(); - // Main event processing loop - // Do something in wasm - // Saved for future usage - // Clean up WASM runtime thread envirnment - wasm_runtime_destroy_thread_env(); -} -#endif - -int ocre_get_event(wasm_exec_env_t exec_env, uint32_t type_offset, uint32_t id_offset, uint32_t port_offset, - uint32_t state_offset, uint32_t extra_offset, uint32_t payload_len_offset) { - wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); - if (!module_inst) { - LOG_ERR("No module instance for exec_env\n"); - return -EINVAL; - } - - uint32_t *type_native = (uint32_t *)wasm_runtime_addr_app_to_native(module_inst, type_offset); - uint32_t *id_native = (uint32_t *)wasm_runtime_addr_app_to_native(module_inst, id_offset); - uint32_t *port_native = (uint32_t *)wasm_runtime_addr_app_to_native(module_inst, port_offset); - uint32_t *state_native = (uint32_t *)wasm_runtime_addr_app_to_native(module_inst, state_offset); - uint32_t *extra_native = (uint32_t *)wasm_runtime_addr_app_to_native(module_inst, extra_offset); - uint32_t *payload_len_native = (uint32_t *)wasm_runtime_addr_app_to_native(module_inst, payload_len_offset); - - if (!type_native || !id_native || !port_native || !state_native || !extra_native || !payload_len_native) { - LOG_ERR("Invalid offsets provided"); - return -EINVAL; - } - - ocre_event_t event; - int ret; - - /* Generic event queue implementation for both platforms */ - core_spinlock_key_t key = core_spinlock_lock(&ocre_event_queue_lock); - ret = core_eventq_peek(&ocre_event_queue, &event); - if (ret != 0) { - core_spinlock_unlock(&ocre_event_queue_lock, key); - return -ENOMSG; - } - - if (event.owner != module_inst) { - core_spinlock_unlock(&ocre_event_queue_lock, key); - return -EPERM; - } - - ret = core_eventq_get(&ocre_event_queue, &event); - if (ret != 0) { - core_spinlock_unlock(&ocre_event_queue_lock, key); - return -ENOENT; - } - - // Send event correctly to WASM - switch (event.type) { - case OCRE_RESOURCE_TYPE_TIMER: { - LOG_DBG("Retrieved Timer event timer_id=%u, owner=%p", event.data.timer_event.timer_id, - (void *)event.owner); - *type_native = event.type; - *id_native = event.data.timer_event.timer_id; - *port_native = 0; - *state_native = 0; - *extra_native = 0; - *payload_len_native = 0; - break; - } - case OCRE_RESOURCE_TYPE_GPIO: { - LOG_DBG("Retrieved Gpio event pin_id=%u, port=%u, state=%u, owner=%p", event.data.gpio_event.pin_id, - event.data.gpio_event.port, event.data.gpio_event.state, (void *)event.owner); - *type_native = event.type; - *id_native = event.data.gpio_event.pin_id; - *port_native = event.data.gpio_event.port; - *state_native = event.data.gpio_event.state; - *extra_native = 0; - *payload_len_native = 0; - break; - } - case OCRE_RESOURCE_TYPE_SENSOR: { - // Not used as we don't use callbacks in sensor API yet - break; - } - case OCRE_RESOURCE_TYPE_MESSAGING: { - LOG_DBG("Retrieved Messaging event: message_id=%u, topic=%s, topic_offset=%u, content_type=%s, " - "content_type_offset=%u, payload_len=%d, owner=%p", - event.data.messaging_event.message_id, event.data.messaging_event.topic, - event.data.messaging_event.topic_offset, event.data.messaging_event.content_type, - event.data.messaging_event.content_type_offset, event.data.messaging_event.payload_len, - (void *)event.owner); - *type_native = event.type; - *id_native = event.data.messaging_event.message_id; - *port_native = event.data.messaging_event.topic_offset; - *state_native = event.data.messaging_event.content_type_offset; - *extra_native = event.data.messaging_event.payload_offset; - *payload_len_native = event.data.messaging_event.payload_len; - break; - } - /* - ================================= - Place to add more resource types - ================================= - */ - default: { - core_spinlock_unlock(&ocre_event_queue_lock, key); - LOG_ERR("Invalid event type: %u", event.type); - return -EINVAL; - } - } - core_spinlock_unlock(&ocre_event_queue_lock, key); - return 0; -} - -int ocre_common_init(void) { - static bool initialized = false; - if (initialized) { - LOG_INF("Common system already initialized"); - return 0; - } - - core_mutex_init(®istry_mutex); - core_slist_init(&module_registry); - - core_eventq_init(&ocre_event_queue, sizeof(ocre_event_t), SIZE_OCRE_EVENT_BUFFER); - - /* Purge any stale events from queue */ - ocre_event_t dummy; - while (core_eventq_get(&ocre_event_queue, &dummy) == 0) { - LOG_INF("Purged stale event from queue"); - } - - /* Temporary platform-specific initialization */ -#ifdef __ZEPHYR__ - /* No additional Zephyr-specific initialization needed */ -#else /* POSIX */ - pthread_mutex_init(&ocre_event_queue_lock.mutex, NULL); -#endif - - ocre_event_queue_initialized = true; -#if EVENT_THREAD_POOL_SIZE > 0 - LOG_INF("ocre_event_queue initialized at %p, size=%d", (void *)&ocre_event_queue, sizeof(ocre_event_t)); - for (int i = 0; i < EVENT_THREAD_POOL_SIZE; i++) { - event_args[i].index = i; - char thread_name[16]; - snprintf(thread_name, sizeof(thread_name), "event_thread_%d", i); - int ret = core_thread_create(&event_threads[i], event_thread_fn, &event_args[i], thread_name, - EVENT_THREAD_STACK_SIZE, 5); - if (ret != 0) { - LOG_ERR("Failed to create thread for event %d", i); - return -1; - } - LOG_INF("Started event thread %s", thread_name); - } -#endif - initialized = true; - common_initialized = true; - - LOG_INF("OCRE common initialized successfully"); - return 0; -} - -void ocre_common_shutdown(void) { -#if EVENT_THREAD_POOL_SIZE > 0 - event_threads_exit = true; - for (int i = EVENT_THREAD_POOL_SIZE; i > 0; i--) { - event_args[i].index = i; - char thread_name[16]; - snprintf(thread_name, sizeof(thread_name), "event_thread_%d", i); - core_thread_destroy(&event_threads[i]); - } -#endif - common_initialized = false; - LOG_INF("OCRE common shutdown successfully"); -} - -int ocre_register_cleanup_handler(ocre_resource_type_t type, ocre_cleanup_handler_t handler) { - if (type >= OCRE_RESOURCE_TYPE_COUNT) { - LOG_ERR("Invalid resource type: %d", type); - return -EINVAL; - } - cleanup_handlers[type] = (struct cleanup_handler){type, handler}; - LOG_INF("Registered cleanup handler for type %d", type); - return 0; -} - -int ocre_register_module(wasm_module_inst_t module_inst) { - if (!module_inst) { - LOG_ERR("Null module instance"); - return -EINVAL; - } - module_node_t *node = core_malloc(sizeof(module_node_t)); - if (!node) { - LOG_ERR("Failed to allocate module node"); - return -ENOMEM; - } - node->ctx.inst = module_inst; - node->ctx.exec_env = wasm_runtime_create_exec_env(module_inst, OCRE_WASM_STACK_SIZE); - if (!node->ctx.exec_env) { - LOG_ERR("Failed to create exec env for module %p", (void *)module_inst); - core_free(node); - return -ENOMEM; - } - node->ctx.in_use = true; - node->ctx.last_activity = core_uptime_get(); - memset(node->ctx.resource_count, 0, sizeof(node->ctx.resource_count)); - memset(node->ctx.dispatchers, 0, sizeof(node->ctx.dispatchers)); - - core_mutex_lock(®istry_mutex); - core_slist_append(&module_registry, &node->node); - core_mutex_unlock(®istry_mutex); - - LOG_INF("Module registered: %p", (void *)module_inst); - return 0; -} - -void ocre_unregister_module(wasm_module_inst_t module_inst) { - if (!module_inst) { - LOG_ERR("Null module instance"); - return; - } - - core_mutex_lock(®istry_mutex); - module_node_t *node, *tmp; - module_node_t *prev = NULL; - CORE_SLIST_FOR_EACH_CONTAINER_SAFE(&module_registry, node, tmp, node) { - if (node->ctx.inst == module_inst) { - ocre_cleanup_module_resources(module_inst); - if (node->ctx.exec_env) { - wasm_runtime_destroy_exec_env(node->ctx.exec_env); - } - core_slist_remove(&module_registry, prev ? &prev->node : NULL, &node->node); - core_free(node); - LOG_INF("Module unregistered: %p", (void *)module_inst); - break; - } - prev = node; - } - core_mutex_unlock(®istry_mutex); -} - -ocre_module_context_t *ocre_get_module_context(wasm_module_inst_t module_inst) { - if (!module_inst) { - LOG_ERR("Null module instance"); - return NULL; - } - core_mutex_lock(®istry_mutex); - for (core_snode_t *current = module_registry.head; current != NULL; current = current->next) { - module_node_t *node = (module_node_t *)((char *)current - offsetof(module_node_t, node)); - if (node->ctx.inst == module_inst) { - node->ctx.last_activity = core_uptime_get(); - core_mutex_unlock(®istry_mutex); - return &node->ctx; - } - } - core_mutex_unlock(®istry_mutex); - LOG_ERR("Module context not found for %p", (void *)module_inst); - return NULL; -} - -int ocre_register_dispatcher(wasm_exec_env_t exec_env, ocre_resource_type_t type, const char *function_name) { - if (!exec_env || !function_name || type >= OCRE_RESOURCE_TYPE_COUNT) { - LOG_ERR("Invalid dispatcher params: exec_env=%p, type=%d, func=%s", (void *)exec_env, type, - function_name ? function_name : "null"); - return -EINVAL; - } - - wasm_module_inst_t module_inst = current_module_tls ? *current_module_tls : wasm_runtime_get_module_inst(exec_env); - - if (!module_inst) { - LOG_ERR("No module instance for event type %d", type); - return -EINVAL; - } - ocre_module_context_t *ctx = ocre_get_module_context(module_inst); - if (!ctx) { - LOG_ERR("Module context not found for %p", (void *)module_inst); - return -EINVAL; - } - LOG_DBG("Attempting to lookup function '%s' in module %p", function_name, (void *)module_inst); - wasm_function_inst_t func = wasm_runtime_lookup_function(module_inst, function_name); - if (!func) { - LOG_ERR("Function %s not found in module %p", function_name, (void *)module_inst); - return -EINVAL; - } - core_mutex_lock(®istry_mutex); - ctx->dispatchers[type] = func; - core_mutex_unlock(®istry_mutex); - LOG_INF("Registered dispatcher for type %d: %s", type, function_name); - return 0; -} - -uint32_t ocre_get_resource_count(wasm_module_inst_t module_inst, ocre_resource_type_t type) { - ocre_module_context_t *ctx = ocre_get_module_context(module_inst); - return ctx ? ctx->resource_count[type] : 0; -} - -void ocre_increment_resource_count(wasm_module_inst_t module_inst, ocre_resource_type_t type) { - ocre_module_context_t *ctx = ocre_get_module_context(module_inst); - if (ctx && type < OCRE_RESOURCE_TYPE_COUNT) { - core_mutex_lock(®istry_mutex); - ctx->resource_count[type]++; - core_mutex_unlock(®istry_mutex); - LOG_INF("Incremented resource count: type=%d, count=%d", type, ctx->resource_count[type]); - } -} - -void ocre_decrement_resource_count(wasm_module_inst_t module_inst, ocre_resource_type_t type) { - ocre_module_context_t *ctx = ocre_get_module_context(module_inst); - if (ctx && type < OCRE_RESOURCE_TYPE_COUNT && ctx->resource_count[type] > 0) { - core_mutex_lock(®istry_mutex); - ctx->resource_count[type]--; - core_mutex_unlock(®istry_mutex); - LOG_INF("Decremented resource count: type=%d, count=%d", type, ctx->resource_count[type]); - } -} - -void ocre_cleanup_module_resources(wasm_module_inst_t module_inst) { - for (int i = 0; i < OCRE_RESOURCE_TYPE_COUNT; i++) { - if (cleanup_handlers[i].handler) { - cleanup_handlers[i].handler(module_inst); - } - } -} - -wasm_module_inst_t ocre_get_current_module(void) { - return current_module_tls ? *current_module_tls : NULL; -} diff --git a/src/ocre/component/component.c b/src/ocre/component/component.c deleted file mode 100644 index daa6121b..00000000 --- a/src/ocre/component/component.c +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -#include "ocre_core_external.h" -#include "component.h" - -void ocre_component_init(struct ocre_component *component) { - core_mq_init(&component->msgq, "/ocre_component_msgq", sizeof(struct ocre_message), MSG_QUEUE_DEPTH); -} - -int ocre_component_send(struct ocre_component *component, struct ocre_message *msg) { - int ret = core_mq_send(&component->msgq, msg, sizeof(struct ocre_message)); - - return ret; -} diff --git a/src/ocre/component/component.h b/src/ocre/component/component.h deleted file mode 100644 index b6d96e7a..00000000 --- a/src/ocre/component/component.h +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef OCRE_COMPONENT_H -#define OCRE_COMPONENT_H - -#include "ocre_core_external.h" -#include - -// can't be higher than /proc/sys/fs/mqueue/msg_max which is typically 10 -#define MSG_QUEUE_DEPTH 10 - -#define COMPONENT_SEND_SIMPLE(c, e) \ - struct ocre_message _msg = {.event = e}; \ - ocre_component_send(c, &_msg) - -struct ocre_component { - struct ocre_message msg; /*!< Message struct for reading messages into */ - core_mq_t msgq; /*!< Message queue to read from */ -}; - -void ocre_component_init(struct ocre_component *component); - -int ocre_component_send(struct ocre_component *component, struct ocre_message *msg); - -#endif // OCRE_COMPONENT_H diff --git a/src/ocre/components/container_supervisor/component_supervisor.yaml b/src/ocre/components/container_supervisor/component_supervisor.yaml deleted file mode 100644 index 2755133e..00000000 --- a/src/ocre/components/container_supervisor/component_supervisor.yaml +++ /dev/null @@ -1,11 +0,0 @@ -component: container_supervisor -events: - - name: QUERY - type: query - - name: INSTALL - type: install - - name: UNINSTALL - type: uninstall - - name: APP_MANAGER_RESPONSE - type: app_manager_response -# Any events not listed get a message type of "base_message" \ No newline at end of file diff --git a/src/ocre/components/container_supervisor/cs_main.c b/src/ocre/components/container_supervisor/cs_main.c deleted file mode 100644 index 2727572f..00000000 --- a/src/ocre/components/container_supervisor/cs_main.c +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include "cs_sm.h" -#include "ocre_core_external.h" - -LOG_MODULE_REGISTER(ocre_cs_component, OCRE_LOG_LEVEL); - -#define OCRE_CS_THREAD_PRIORITY 0 - -static core_thread_t ocre_cs_thread; -static int ocre_cs_thread_initialized = 0; - -static void ocre_cs_main(void *ctx) { - wasm_runtime_init_thread_env(); - LOG_INF("Container Supervisor started."); - int ret = _ocre_cs_run(ctx); - LOG_ERR("Container Supervisor exited: %d", ret); - wasm_runtime_destroy_thread_env(); -} - -// Function to start the thread -void start_ocre_cs_thread(ocre_cs_ctx *ctx) { - if (ocre_cs_thread_initialized) { - LOG_WRN("Container Supervisor thread is already running."); - return; - } - int ret = core_thread_create(&ocre_cs_thread, ocre_cs_main, ctx, "Ocre Container Supervisor", OCRE_CS_THREAD_STACK_SIZE, OCRE_CS_THREAD_PRIORITY); - if (ret != 0) { - LOG_ERR("Failed to create Container Supervisor thread: %d", ret); - return; - } - ocre_cs_thread_initialized = 1; -} - -void destroy_ocre_cs_thread(void) { - if (!ocre_cs_thread_initialized) { - LOG_ERR("Container Supervisor thread is not running.\n"); - return; - } - core_thread_destroy(&ocre_cs_thread); - ocre_cs_thread_initialized = 0; -} diff --git a/src/ocre/components/container_supervisor/cs_sm.c b/src/ocre/components/container_supervisor/cs_sm.c deleted file mode 100644 index 9f2bc585..00000000 --- a/src/ocre/components/container_supervisor/cs_sm.c +++ /dev/null @@ -1,169 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include "ocre_core_external.h" -LOG_MODULE_DECLARE(ocre_cs_component, OCRE_LOG_LEVEL); -#ifdef CONFIG_OCRE_SENSORS -#include "../../ocre_sensors/ocre_sensors.h" -#endif -#include "cs_sm.h" -#include "cs_sm_impl.h" -#include - -// Define state machine and component -struct ocre_component ocre_cs_component; -state_machine_t ocre_cs_state_machine; - -/* State event handlers */ -static void runtime_uninitialized_entry(void *o) { -#if OCRE_CS_DEBUG_ON - LOG_INF("HELLO runtime_uninitialized_entry"); -#endif - struct ocre_message event = {.event = EVENT_CS_INITIALIZE}; - ocre_component_send(&ocre_cs_component, &event); -} - -static enum smf_state_result runtime_uninitialized_run(void *o) { -#if OCRE_CS_DEBUG_ON - LOG_INF("HELLO runtime_uninitialized_run"); -#endif - struct ocre_message *msg = SM_GET_EVENT(o); - - switch (msg->event) { - case EVENT_CS_INITIALIZE: -#if OCRE_CS_DEBUG_ON - LOG_INF("Transitioning from state STATE_RUNTIME_UNINITIALIZED_RUN to state STATE_RUNTIME_RUNNING"); -#endif - sm_transition(&ocre_cs_state_machine, STATE_RUNTIME_RUNNING); - break; - default: - break; - } - SM_MARK_EVENT_HANDLED(o); - return SMF_EVENT_HANDLED; -} - -static void runtime_running_entry(void *o) { -#if OCRE_CS_DEBUG_ON - LOG_INF("HELLO runtime_running_entry"); -#endif -} - -static enum smf_state_result runtime_running_run(void *o) { -#if OCRE_CS_DEBUG_ON - LOG_INF("HELLO runtime_running_run"); -#endif - struct ocre_message *msg = SM_GET_EVENT(o); - ocre_cs_ctx *ctx = SM_GET_CUSTOM_CTX(o); - ocre_container_runtime_cb callback = NULL; - switch (msg->event) { - case EVENT_CREATE_CONTAINER: { - LOG_INF("EVENT_CREATE_CONTAINER"); - - if (msg->containerId < 0 || msg->containerId >= CONFIG_MAX_CONTAINERS) { - LOG_ERR("Invalid container ID: %d", msg->containerId); - break; - } - - if (CS_create_container(&ctx->containers[msg->containerId]) == CONTAINER_STATUS_CREATED) { - LOG_INF("Created container in slot:%d", msg->containerId); - } else { - LOG_ERR("Failed to create container in slot:%d", msg->containerId); - } - break; - } - case EVENT_RUN_CONTAINER: { - LOG_INF("EVENT_RUN_CONTAINER"); - - if (msg->containerId < 0 || msg->containerId >= CONFIG_MAX_CONTAINERS) { - LOG_ERR("Invalid container ID: %d", msg->containerId); - break; - } - - if (CS_run_container(&ctx->containers[msg->containerId]) == CONTAINER_STATUS_RUNNING) { - LOG_INF("Started container in slot:%d", msg->containerId); - } else { - LOG_ERR("Failed to run container in slot:%d", msg->containerId); - } - break; - } - case EVENT_STOP_CONTAINER: { - LOG_INF("EVENT_STOP_CONTAINER"); - - if (msg->containerId < 0 || msg->containerId >= CONFIG_MAX_CONTAINERS) { - LOG_ERR("Invalid container ID: %d", msg->containerId); - break; - } - - if (CS_stop_container(&ctx->containers[msg->containerId], callback) == CONTAINER_STATUS_STOPPED) { - LOG_INF("Stopped container in slot:%d", msg->containerId); - } else { - LOG_ERR("Failed to stop container in slot:%d", msg->containerId); - } - break; - } - case EVENT_DESTROY_CONTAINER: { - LOG_INF("EVENT_DESTROY_CONTAINER"); - - if (msg->containerId < 0 || msg->containerId >= CONFIG_MAX_CONTAINERS) { - LOG_ERR("Invalid container ID: %d", msg->containerId); - break; - } - - if (CS_destroy_container(&ctx->containers[msg->containerId], callback) == CONTAINER_STATUS_DESTROYED) { - LOG_INF("Destroyed container in slot:%d", msg->containerId); - } else { - LOG_ERR("Failed to destroy container in slot:%d", msg->containerId); - } - break; - } - case EVENT_RESTART_CONTAINER: { - LOG_INF("EVENT_RESTART_CONTAINER"); - if (msg->containerId < 0 || msg->containerId >= CONFIG_MAX_CONTAINERS) { - LOG_ERR("Invalid container ID: %d", msg->containerId); - break; - } - - if (CS_restart_container(&ctx->containers[msg->containerId], callback) == CONTAINER_STATUS_RUNNING) { - LOG_INF("Container in slot:%d restarted successfully", msg->containerId); - } else { - LOG_ERR("Failed to restart container in slot:%d", msg->containerId); - } - break; - } - case EVENT_CS_DESTROY: - LOG_INF("EVENT_CS_DESTROY"); - sm_transition(&ocre_cs_state_machine, STATE_RUNTIME_UNINITIALIZED); - break; - default: - break; - } - - SM_MARK_EVENT_HANDLED(o); - return SMF_EVENT_HANDLED; -} - -static enum smf_state_result runtime_error_run(void *o) { -#if OCRE_CS_DEBUG_ON - LOG_INF("HELLO runtime_error_run"); -#endif - return SMF_EVENT_HANDLED; -} - -static const struct smf_state hsm[] = { - [STATE_RUNTIME_UNINITIALIZED] = - SMF_CREATE_STATE(runtime_uninitialized_entry, runtime_uninitialized_run, NULL, NULL, NULL), - [STATE_RUNTIME_RUNNING] = SMF_CREATE_STATE(runtime_running_entry, runtime_running_run, NULL, NULL, NULL), - [STATE_RUNTIME_ERROR] = SMF_CREATE_STATE(NULL, runtime_error_run, NULL, NULL, NULL)}; - -// Entry point for running the state machine -int _ocre_cs_run(ocre_cs_ctx *ctx) { - ocre_component_init(&ocre_cs_component); - sm_init(&ocre_cs_state_machine, &ocre_cs_component.msgq, &ocre_cs_component.msg, ctx, hsm); - return sm_run(&ocre_cs_state_machine, STATE_RUNTIME_UNINITIALIZED); -} diff --git a/src/ocre/components/container_supervisor/cs_sm.h b/src/ocre/components/container_supervisor/cs_sm.h deleted file mode 100644 index 4ba02bc3..00000000 --- a/src/ocre/components/container_supervisor/cs_sm.h +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef OCRE_IWASM_H -#define OCRE_IWASM_H - -#include "ocre_core_external.h" - -#include -#include -#include - -#define OCRE_CS_DEBUG_ON 0 - -extern struct ocre_component ocre_cs_component; -extern state_machine_t ocre_cs_state_machine; // TODO This needs to get encapsulated into the - // sm. it's only here so components can operate - // timers. timers need to be encapsulated. - -enum CONTAINER_RUNTIME_STATE { - STATE_RUNTIME_UNINITIALIZED, - STATE_RUNTIME_RUNNING, - STATE_RUNTIME_ERROR -}; - -enum OCRE_CS_EVENT { - // CS Events - EVENT_CS_INITIALIZE, - EVENT_CS_DESTROY, - EVENT_CS_ERROR, - - // Container related events - EVENT_CREATE_CONTAINER, - EVENT_RUN_CONTAINER, - EVENT_STOP_CONTAINER, - EVENT_DESTROY_CONTAINER, - EVENT_RESTART_CONTAINER, - EVENT_ERROR -}; -void start_ocre_cs_thread(ocre_cs_ctx *ctx); - -void destroy_ocre_cs_thread(void); - -int _ocre_cs_run(); - -#endif diff --git a/src/ocre/components/container_supervisor/cs_sm_impl.c b/src/ocre/components/container_supervisor/cs_sm_impl.c deleted file mode 100644 index 29b2cefb..00000000 --- a/src/ocre/components/container_supervisor/cs_sm_impl.c +++ /dev/null @@ -1,612 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include "ocre_core_external.h" - -#ifdef CONFIG_OCRE_TIMER -#include "ocre_timers/ocre_timer.h" -#endif -#ifdef CONFIG_OCRE_GPIO -#include "ocre_gpio/ocre_gpio.h" -#endif -#ifdef CONFIG_OCRE_CONTAINER_MESSAGING -#include "ocre_messaging/ocre_messaging.h" -#endif -#if defined(CONFIG_OCRE_TIMER) || defined(CONFIG_OCRE_GPIO) || defined(CONFIG_OCRE_SENSORS) || \ - defined(CONFIG_OCRE_CONTAINER_MESSAGING) -#include "api/ocre_common.h" -#endif - - -#ifdef CONFIG_OCRE_SHELL -#include "ocre/shell/ocre_shell.h" -#endif - -LOG_MODULE_DECLARE(ocre_cs_component, OCRE_LOG_LEVEL); - -#include "../../../../../wasm-micro-runtime/core/iwasm/include/lib_export.h" -#include "bh_log.h" -#include -#include "cs_sm.h" -#include "cs_sm_impl.h" - -// Thread pool for container execution -#define CONTAINER_THREAD_POOL_SIZE 4 -static core_thread_t container_threads[CONTAINER_THREAD_POOL_SIZE]; -static bool container_thread_active[CONTAINER_THREAD_POOL_SIZE] = {false}; - -static core_mutex_t container_mutex; - -// Arguments for container threads -struct container_thread_args { - ocre_container_t *container; -}; - -#ifdef CONFIG_OCRE_MEMORY_CHECK_ENABLED -static size_t ocre_get_available_memory(void) { -#ifdef CONFIG_HEAP_MEM_POOL_SIZE - struct k_heap_stats stats; - k_heap_sys_get_stats(&stats); - return stats.free_bytes; -#else - extern char *z_malloc_mem_pool_area_start; - extern char *z_malloc_mem_pool_area_end; - extern struct sys_mem_pool_base z_malloc_mem_pool; - - size_t total_size = z_malloc_mem_pool_area_end - z_malloc_mem_pool_area_start; - size_t used_size = sys_mem_pool_get_used_size(&z_malloc_mem_pool); - return total_size - used_size; -#endif -} -#endif - -#ifdef CONFIG_OCRE_SHARED_HEAP -// Shared heap for memory-mapped access -wasm_shared_heap_t _shared_heap = NULL; -#ifdef CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL -uint8 preallocated_buf[CONFIG_OCRE_SHARED_HEAP_BUF_SIZE]; -#endif -#endif - -static bool validate_container_memory(ocre_container_t *container) { -#ifdef CONFIG_OCRE_MEMORY_CHECK_ENABLED - size_t requested_heap = container->ocre_container_data.heap_size; - size_t requested_stack = container->ocre_container_data.stack_size; - - if (requested_heap == 0 || requested_heap > CONFIG_OCRE_CONTAINER_DEFAULT_HEAP_SIZE) { - LOG_ERR("Invalid heap size requested: %zu bytes", requested_heap); - return false; - } - - if (requested_stack == 0 || requested_stack > CONFIG_OCRE_CONTAINER_DEFAULT_STACK_SIZE) { - LOG_ERR("Invalid stack size requested: %zu bytes", requested_stack); - return false; - } - - size_t available_memory = ocre_get_available_memory(); - size_t required_memory = requested_heap + requested_stack + sizeof(WASMExecEnv); - - if (available_memory < required_memory) { - LOG_ERR("Insufficient memory for container %d: required %zu bytes, available %zu bytes", - container->container_ID, required_memory, available_memory); - return false; - } - LOG_INF("Memory check passed: %zu bytes required, %zu bytes available", required_memory, available_memory); - - container->ocre_runtime_arguments.stack_size = requested_stack; - container->ocre_runtime_arguments.heap_size = requested_heap; -#else - container->ocre_runtime_arguments.stack_size = CONFIG_OCRE_CONTAINER_DEFAULT_STACK_SIZE; - container->ocre_runtime_arguments.heap_size = CONFIG_OCRE_CONTAINER_DEFAULT_HEAP_SIZE; -#endif - return true; -} - -// Container thread entry function -static void container_thread_entry(void *args) { - struct container_thread_args *container_args = args; - ocre_container_t *container = container_args->container; - wasm_module_inst_t module_inst = container->ocre_runtime_arguments.module_inst; - - // Initialize WASM runtime thread environment - wasm_runtime_init_thread_env(); - - LOG_INF("Container thread %d started", container->container_ID); - -#if defined(CONFIG_OCRE_TIMER) || defined(CONFIG_OCRE_GPIO) || defined(CONFIG_OCRE_SENSORS) || \ - defined(CONFIG_OCRE_CONTAINER_MESSAGING) - // Set TLS for the container's WASM module - current_module_tls = &module_inst; -#endif - // Run the WASM main function - bool success = wasm_application_execute_main(module_inst, 0, NULL); - // Update container status - if (container->container_runtime_status != CONTAINER_STATUS_STOPPED) - container->container_runtime_status = success ? CONTAINER_STATUS_STOPPED : CONTAINER_STATUS_ERROR; - // Cleanup sequence - core_mutex_lock(&container->lock); - { - // Cleanup subsystems -#ifdef CONFIG_OCRE_TIMER - ocre_timer_cleanup_container(module_inst); -#endif -#ifdef CONFIG_OCRE_GPIO - ocre_gpio_cleanup_container(module_inst); -#endif -#ifdef CONFIG_OCRE_CONTAINER_MESSAGING - ocre_messaging_cleanup_container(module_inst); -#endif - - // Clear thread tracking - container_thread_active[container->container_ID] = false; -#if defined(CONFIG_OCRE_TIMER) || defined(CONFIG_OCRE_GPIO) || defined(CONFIG_OCRE_SENSORS) || \ - defined(CONFIG_OCRE_CONTAINER_MESSAGING) - // Clear TLS - current_module_tls = NULL; -#endif - - } - core_mutex_unlock(&container->lock); - - LOG_INF("Container thread %d exited cleanly", container->container_ID); - - // Clean up WASM runtime thread environment - wasm_runtime_destroy_thread_env(); - core_free(args); // Free the dynamically allocated args -} - -static int get_available_thread(void) { - for (int i = 0; i < CONTAINER_THREAD_POOL_SIZE; i++) { - if (!container_thread_active[i]) { - return i; - } - } - return -1; -} - -static int load_binary_to_buffer_fs(ocre_runtime_arguments_t *container_arguments, - ocre_container_data_t *container_data) { - int ret = 0; - size_t file_size = 0; - void *file_handle = NULL; - char filepath[FILE_PATH_MAX]; - - - ret = core_construct_filepath(filepath, sizeof(filepath), container_data->sha256); - if (ret < 0) { - LOG_ERR("Failed to construct filepath for %s: %d", container_data->sha256, ret); - return ret; - } - ret = core_filestat(filepath, &file_size); - if (ret < 0) { - LOG_ERR("Failed to get file status for %s: %d", filepath, ret); - return ret; - } - - container_arguments->size = file_size; - container_arguments->buffer = user_malloc(file_size); - if (!container_arguments->buffer) { - LOG_ERR("Failed to allocate memory for container binary from PSRAM."); - return -ENOMEM; - } - - LOG_INF("File path: %s, size: %lu", filepath, (long unsigned int)file_size); - - ret = core_fileopen(filepath, &file_handle); - if (ret < 0) { - LOG_ERR("Failed to open file %s: %d", filepath, ret); - user_free(container_arguments->buffer); - return ret; - } - - ret = core_fileread(file_handle, container_arguments->buffer, file_size); - if (ret < 0) { - LOG_ERR("Failed to read file %s: %d", filepath, ret); - core_fileclose(file_handle); - user_free(container_arguments->buffer); - return ret; - } - - ret = core_fileclose(file_handle); - if (ret < 0) { - LOG_ERR("Failed to close file %s: %d", filepath, ret); - user_free(container_arguments->buffer); - return ret; - } - return 0; -} - -int CS_ctx_init(ocre_cs_ctx *ctx) { - for (int i = 0; i < CONFIG_MAX_CONTAINERS; i++) { - core_mutex_init(&ctx->containers[i].lock); - ctx->containers[i].container_runtime_status = CONTAINER_STATUS_UNKNOWN; - ctx->containers[i].ocre_container_data.heap_size = CONFIG_OCRE_CONTAINER_DEFAULT_HEAP_SIZE; - ctx->containers[i].ocre_container_data.stack_size = CONFIG_OCRE_CONTAINER_DEFAULT_STACK_SIZE; - memset(ctx->containers[i].ocre_container_data.name, 0, sizeof(ctx->containers[i].ocre_container_data.name)); - memset(ctx->containers[i].ocre_container_data.sha256, 0, sizeof(ctx->containers[i].ocre_container_data.sha256)); - ctx->containers[i].ocre_container_data.timers = 0; - ctx->containers[i].container_ID = i; - } -#ifdef CONFIG_OCRE_SHELL - register_ocre_shell(ctx); -#endif - core_mutex_init(&container_mutex); - return 0; -} - -#if WASM_MEM_ALLOC_WITH_USER_DATA || WASM_MEM_ALLOC_WITH_USAGE -#error user allocator not compatible with WASM_MEM_ALLOC_WITH_USER_DATA or WASM_MEM_ALLOC_WITH_USAGE -#endif - -ocre_container_runtime_status_t CS_runtime_init(ocre_cs_ctx *ctx, ocre_container_init_arguments_t *args) { - RuntimeInitArgs init_args; - memset(&init_args, 0, sizeof(RuntimeInitArgs)); - init_args.mem_alloc_type = Alloc_With_Allocator; - init_args.mem_alloc_option.allocator.malloc_func = user_malloc; - init_args.mem_alloc_option.allocator.free_func = user_free; - init_args.mem_alloc_option.allocator.realloc_func = user_realloc; - init_args.native_module_name = "env"; - init_args.n_native_symbols = ocre_api_table_size; - init_args.native_symbols = ocre_api_table; - - if (!wasm_runtime_full_init(&init_args)) { - LOG_ERR("Failed to initialize the WASM runtime"); - return RUNTIME_STATUS_ERROR; - } - - bh_log_set_verbose_level(BH_LOG_LEVEL_WARNING); - - if (!wasm_runtime_register_natives("env", ocre_api_table, ocre_api_table_size)) { - LOG_ERR("Failed to register the API's"); - return RUNTIME_STATUS_ERROR; - } -#ifdef CONFIG_OCRE_TIMER - ocre_timer_init(); -#endif -#ifdef CONFIG_OCRE_CONTAINER_MESSAGING - ocre_messaging_init(); -#endif -#ifdef CONFIG_OCRE_SHARED_HEAP - SharedHeapInitArgs heap_init_args; - memset(&heap_init_args, 0, sizeof(heap_init_args)); - -#ifdef CONFIG_OCRE_SHARED_HEAP_BUF_PHYSICAL - // Physical mode - map hardware register address - heap_init_args.pre_allocated_addr = (void *)CONFIG_OCRE_SHARED_HEAP_BUF_ADDRESS; - LOG_INF("Creating physical memory mapping at 0x%08X (hardware registers)", - CONFIG_OCRE_SHARED_HEAP_BUF_ADDRESS); -#elif CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL - // Virtual mode - allocate from RAM - heap_init_args.pre_allocated_addr = preallocated_buf; - LOG_INF("Creating virtual shared heap in RAM, size=%d bytes", - CONFIG_OCRE_SHARED_HEAP_BUF_SIZE); -#endif - heap_init_args.size = CONFIG_OCRE_SHARED_HEAP_BUF_SIZE; - _shared_heap = wasm_runtime_create_shared_heap(&heap_init_args); - - if (!_shared_heap) { - LOG_ERR("Create preallocated shared heap failed"); - return RUNTIME_STATUS_ERROR; - } -#endif - - storage_heap_init(); - return RUNTIME_STATUS_INITIALIZED; -} - -ocre_container_runtime_status_t CS_runtime_destroy(void) { - // Signal event threads to exit gracefully -#if defined(CONFIG_OCRE_TIMER) || defined(CONFIG_OCRE_GPIO) || defined(CONFIG_OCRE_SENSORS) || \ - defined(CONFIG_OCRE_CONTAINER_MESSAGING) - ocre_common_shutdown(); -#endif - - // Abort any active container threads - for (int i = 0; i < CONTAINER_THREAD_POOL_SIZE; i++) { - if (container_thread_active[i]) { - core_thread_destroy(&container_threads[i]); - container_thread_active[i] = false; - } - } - return RUNTIME_STATUS_DESTROYED; -} - -ocre_container_status_t CS_create_container(ocre_container_t *container) { - uint32_t curr_container_ID = container->container_ID; - ocre_container_data_t *curr_container_data = &container->ocre_container_data; - ocre_runtime_arguments_t *curr_container_arguments = &container->ocre_runtime_arguments; - - if (container->container_runtime_status == CONTAINER_STATUS_STOPPED) { - LOG_WRN("Container %d is in STOPPED state, destroying it before reuse", curr_container_ID); - CS_destroy_container(container, NULL); - } - - if (container->container_runtime_status != CONTAINER_STATUS_UNKNOWN && - container->container_runtime_status != CONTAINER_STATUS_DESTROYED) { - LOG_ERR("Cannot create container again container with ID: %d, already exists", curr_container_ID); - return CONTAINER_STATUS_ERROR; - } - - if (!validate_container_memory(container)) { - LOG_ERR("Memory check not passed"); - return CONTAINER_STATUS_ERROR; - } - - LOG_INF("Allocating memory for container %d", curr_container_ID); - int ret = load_binary_to_buffer_fs(curr_container_arguments, curr_container_data); - if (ret < 0) { - LOG_ERR("Failed to load binary to buffer: %d", ret); - return CONTAINER_STATUS_ERROR; - } - LOG_INF("Loaded binary to buffer for container %d", curr_container_ID); - - curr_container_arguments->module = - wasm_runtime_load(curr_container_arguments->buffer, curr_container_arguments->size, - curr_container_arguments->error_buf, sizeof(curr_container_arguments->error_buf)); - if (!curr_container_arguments->module) { - LOG_ERR("Failed to load WASM module: %s", curr_container_arguments->error_buf); - user_free(curr_container_arguments->buffer); - return CONTAINER_STATUS_ERROR; - } - - container->container_runtime_status = CONTAINER_STATUS_CREATED; - LOG_WRN("Created container:%d", curr_container_ID); - return container->container_runtime_status; -} - -ocre_container_status_t CS_run_container(ocre_container_t *container) { - uint32_t curr_container_ID = container->container_ID; - ocre_runtime_arguments_t *curr_container_arguments = &container->ocre_runtime_arguments; - - if (container->container_runtime_status == CONTAINER_STATUS_RUNNING) { - LOG_WRN("Container status is already in RUNNING state"); - return CONTAINER_STATUS_RUNNING; - } - - if (container->container_runtime_status != CONTAINER_STATUS_CREATED && - container->container_runtime_status != CONTAINER_STATUS_STOPPED) { - LOG_ERR("Container (ID: %d), is not in a valid state to run", curr_container_ID); - container->container_runtime_status = CONTAINER_STATUS_ERROR; - return CONTAINER_STATUS_ERROR; - } - - #ifdef CONFIG_OCRE_NETWORKING - #define ADDRESS_POOL_SIZE 1 - const char *addr_pool[ADDRESS_POOL_SIZE] = { - "0.0.0.0/0", - }; - wasm_runtime_set_wasi_addr_pool(curr_container_arguments->module, addr_pool, ADDRESS_POOL_SIZE); - /** - * Configure which domain names a WebAssembly module is allowed to resolve via DNS lookups - * ns_lookup_pool: An array of domain name patterns (e.g., "example.com", "*.example.com", or "*" for any domain) - */ - - const char *ns_lookup_pool[] = { - "*" - }; - wasm_runtime_set_wasi_ns_lookup_pool(curr_container_arguments->module, ns_lookup_pool, sizeof(ns_lookup_pool) / sizeof(ns_lookup_pool[0])); - #endif - - #ifdef CONFIG_OCRE_CONTAINER_FILESYSTEM - // Simple for now: map CONTAINER_FS_PATH to / - // TODO: eventually every container should probably have its own root folder, - // however wasm_runtime_set_wasi_args expects constant values. - #define DIR_LIST_SIZE 1 - static const char *dir_map_list[DIR_LIST_SIZE] = { - "/::" CONTAINER_FS_PATH - }; - wasm_runtime_set_wasi_args(curr_container_arguments->module, - NULL, 0, - dir_map_list, DIR_LIST_SIZE, - NULL, 0, NULL, 0); - #endif - - if (curr_container_arguments->module_inst) { - LOG_INF("WASM runtime already instantiated for container:%d", curr_container_ID); - } else { - LOG_INF("Instantiating WASM runtime for container:%d", curr_container_ID); - curr_container_arguments->module_inst = - wasm_runtime_instantiate(curr_container_arguments->module, curr_container_arguments->stack_size, - curr_container_arguments->heap_size, curr_container_arguments->error_buf, - sizeof(curr_container_arguments->error_buf)); - if (!curr_container_arguments->module_inst) { - LOG_ERR("Failed to instantiate WASM module: %s, for containerID= %d", curr_container_arguments->error_buf, - curr_container_ID); - wasm_runtime_unload(curr_container_arguments->module); - user_free(curr_container_arguments->buffer); - return CONTAINER_STATUS_ERROR; - } -#if defined(CONFIG_OCRE_TIMER) || defined(CONFIG_OCRE_GPIO) || defined(CONFIG_OCRE_SENSORS) || \ - defined(CONFIG_OCRE_CONTAINER_MESSAGING) - ocre_register_module(curr_container_arguments->module_inst); -#endif -#ifdef CONFIG_OCRE_SHARED_HEAP - LOG_INF("Attaching shared heap to container %d", curr_container_ID); - /* attach module instance to the shared heap */ - if (!wasm_runtime_attach_shared_heap(curr_container_arguments->module_inst, _shared_heap)) { - LOG_ERR("Attach shared heap failed."); - return CONTAINER_STATUS_ERROR; - } - -#ifdef CONFIG_OCRE_SHARED_HEAP_BUF_PHYSICAL - // For physical mode, get the base address from the shared heap itself - // The WASM address space already knows about the physical mapping - uint32 shared_heap_base_addr = wasm_runtime_addr_native_to_app( - curr_container_arguments->module_inst, - (void*)CONFIG_OCRE_SHARED_HEAP_BUF_ADDRESS); - LOG_INF("Physical shared heap base address in app: 0x%x", shared_heap_base_addr); -#elif CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL - // For virtual mode, convert the allocated buffer address - uint32 shared_heap_base_addr = wasm_runtime_addr_native_to_app( - curr_container_arguments->module_inst, - preallocated_buf); - LOG_INF("Virtual shared heap base address in app: 0x%x", shared_heap_base_addr); -#endif - - if (shared_heap_base_addr == 0) { - LOG_ERR("Failed to get shared heap WASM address!"); - return CONTAINER_STATUS_ERROR; - } -#endif - } - core_mutex_lock(&container_mutex); - int thread_idx = get_available_thread(); - if (thread_idx == -1) { - LOG_ERR("No available threads for container %d", curr_container_ID); - container->container_runtime_status = CONTAINER_STATUS_ERROR; - core_mutex_unlock(&container_mutex); - return CONTAINER_STATUS_ERROR; - } - - // Allocate thread arguments dynamically - struct container_thread_args *args = core_malloc(sizeof(struct container_thread_args)); - if (!args) { - LOG_ERR("Failed to allocate thread args for container %d", curr_container_ID); - container->container_runtime_status = CONTAINER_STATUS_ERROR; - core_mutex_unlock(&container_mutex); - return CONTAINER_STATUS_ERROR; - } - args->container = container; - - // Create and start a new thread for the container - char thread_name[16]; - snprintf(thread_name, sizeof(thread_name), "container_%d", curr_container_ID); - container_threads[thread_idx].user_options = curr_container_ID; - int ret = core_thread_create(&container_threads[thread_idx], container_thread_entry, args, thread_name, - CONTAINER_THREAD_STACK_SIZE, 5); - - if (ret != 0) { - LOG_ERR("Failed to create thread for container %d", curr_container_ID); - container->container_runtime_status = CONTAINER_STATUS_ERROR; - - core_free(args); // Free the dynamically allocated args - - core_mutex_unlock(&container_mutex); - return CONTAINER_STATUS_ERROR; - } - - container_thread_active[thread_idx] = true; - core_mutex_unlock(&container_mutex); - - container->container_runtime_status = CONTAINER_STATUS_RUNNING; - LOG_WRN("Running container:%d in dedicated thread", curr_container_ID); - return CONTAINER_STATUS_RUNNING; -} - -ocre_container_status_t CS_get_container_status(ocre_cs_ctx *ctx, int container_id) { - if (container_id < 0 || container_id >= CONFIG_MAX_CONTAINERS) { - LOG_ERR("Invalid container ID: %d", container_id); - return CONTAINER_STATUS_ERROR; - } - - return ctx->containers[container_id].container_runtime_status; -} - -ocre_container_status_t CS_stop_container(ocre_container_t *container, ocre_container_runtime_cb callback) { - uint32_t curr_container_ID = container->container_ID; - ocre_runtime_arguments_t *curr_container_arguments = &container->ocre_runtime_arguments; - if (container->container_runtime_status == CONTAINER_STATUS_STOPPED) { - LOG_WRN("Container status is already in STOP state"); - return CONTAINER_STATUS_STOPPED; - } - core_mutex_lock(&container->lock); - { - LOG_INF("Stopping container %d from state %d", curr_container_ID, container->container_runtime_status); - - for (int i = 0; i < CONTAINER_THREAD_POOL_SIZE; i++) { - if (container_thread_active[i] && container_threads[i].user_options == curr_container_ID) { -#if defined(CONFIG_OCRE_CONTAINER_WAMR_TERMINATION) -/** - * wasm_runtime_terminate uses POSIX signals to terminate the thread from the outside; calling core_thread_destroy - * would try to destroy again the thread, and pthread_join() will never return, while freeing the stack would cause - * segfault. This separation is needed to distinguish platform supported by wamr with this features, - * from those which aren't. Since this function exists on those platforms, but stubbed, config parameter is used. - */ - wasm_runtime_terminate(curr_container_arguments->module_inst); -#else - core_thread_destroy(&container_threads[i]); -#endif - container_thread_active[i] = false; - } - } -#ifdef CONFIG_OCRE_TIMER - ocre_timer_cleanup_container(curr_container_arguments->module_inst); -#endif -#ifdef CONFIG_OCRE_GPIO - ocre_gpio_cleanup_container(curr_container_arguments->module_inst); -#endif -#ifdef CONFIG_OCRE_CONTAINER_MESSAGING - ocre_messaging_cleanup_container(curr_container_arguments->module_inst); -#endif - -#if defined(CONFIG_OCRE_TIMER) || defined(CONFIG_OCRE_GPIO) || defined(CONFIG_OCRE_SENSORS) || \ - defined(CONFIG_OCRE_CONTAINER_MESSAGING) - ocre_unregister_module(curr_container_arguments->module_inst); -#endif - - if (curr_container_arguments->module_inst) { - wasm_runtime_deinstantiate(curr_container_arguments->module_inst); - curr_container_arguments->module_inst = NULL; - } - - container->container_runtime_status = CONTAINER_STATUS_STOPPED; - } - core_mutex_unlock(&container->lock); - - if (callback) { - callback(); - } - return CONTAINER_STATUS_STOPPED; -} - -ocre_container_status_t CS_destroy_container(ocre_container_t *container, ocre_container_runtime_cb callback) { - if (container->container_runtime_status != CONTAINER_STATUS_STOPPED) { - CS_stop_container(container, NULL); - } - - core_mutex_lock(&container->lock); - { - LOG_INF("Destroying container %d", container->container_ID); - if (container->ocre_runtime_arguments.module) { - wasm_runtime_unload(container->ocre_runtime_arguments.module); - container->ocre_runtime_arguments.module = NULL; - } - - if (container->ocre_runtime_arguments.buffer) { - user_free(container->ocre_runtime_arguments.buffer); - container->ocre_runtime_arguments.buffer = NULL; - } - - memset(&container->ocre_container_data, 0, sizeof(ocre_container_data_t)); - container->container_runtime_status = CONTAINER_STATUS_DESTROYED; - } - core_mutex_unlock(&container->lock); - - if (callback) { - callback(); - } - return CONTAINER_STATUS_DESTROYED; -} - -ocre_container_status_t CS_restart_container(ocre_container_t *container, ocre_container_runtime_cb callback) { - ocre_container_status_t status = CS_stop_container(container, NULL); - if (status != CONTAINER_STATUS_STOPPED) { - LOG_ERR("Failed to stop container: %d", container->container_ID); - return CONTAINER_STATUS_ERROR; - } - - status = CS_run_container(container); - if (status != CONTAINER_STATUS_RUNNING) { - LOG_ERR("Failed to start container: %d", container->container_ID); - return CONTAINER_STATUS_ERROR; - } - if (callback) { - callback(); - } - - return CONTAINER_STATUS_RUNNING; -} diff --git a/src/ocre/components/container_supervisor/cs_sm_impl.h b/src/ocre/components/container_supervisor/cs_sm_impl.h deleted file mode 100644 index f3cae177..00000000 --- a/src/ocre/components/container_supervisor/cs_sm_impl.h +++ /dev/null @@ -1,119 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef OCRE_CS_SM_IMPL_H -#define OCRE_CS_SM_IMPL_H - -#include "ocre_core_external.h" -#include "api/ocre_api.h" -#include - -// ----------------------------------------------------------------------------- -// Function prototypes for OCRE container runtime and container management -// ----------------------------------------------------------------------------- - -// RUNTIME - -/** - * @brief Initialize the container runtime environment. - * - * This function sets up the runtime environment for OCRE containers, preparing necessary resources and state. - * - * @param ctx Pointer to the container runtime context. - * @param args Pointer to initialization arguments. - * @return ocre_container_runtime_status_t Status of the initialization (e.g., success or error code). - */ -ocre_container_runtime_status_t CS_runtime_init(ocre_cs_ctx *ctx, ocre_container_init_arguments_t *args); - -/** - * @brief Destroy the container runtime environment. - * - * This function cleans up and releases any resources used by the container runtime. - * - * @return ocre_container_runtime_status_t Status of the destruction process. - */ -ocre_container_runtime_status_t CS_runtime_destroy(void); - -// CONTAINER - -/** - * @brief Create a new container. - * - * This function creates a container with the specified container ID and associates it with the context. - * - * @param ctx Pointer to the container runtime context. - * @param container_id The ID of the container to be created. - * @return ocre_container_status_t Status of the container creation. - */ -ocre_container_status_t CS_create_container(ocre_container_t *container); - -/** - * @brief Run a container. - * - * This function starts the execution of a container based on its container ID. - * - * @param ctx Pointer to the container runtime context. - * @param container_id The ID of the container to be run. - * @return ocre_container_status_t Status of the container execution. - */ -ocre_container_status_t CS_run_container(ocre_container_t *ctx); - -/** - * @brief Get the status of a container. - * - * This function retrieves the current status of the container. - * - * @param ctx Pointer to the container runtime context. - * @param container_id The ID of the container whose status is being queried. - * @return ocre_container_status_t Status of the container. - */ -ocre_container_status_t CS_get_container_status(ocre_cs_ctx *ctx, int container_id); - -/** - * @brief Stop a container. - * - * This function stops the execution of the container and invokes a callback function when completed. - * - * @param container_id The ID of the container to be stopped. - * @param callback Callback function to be invoked after stopping the container. - * @return ocre_container_status_t Status of the stop operation. - */ -ocre_container_status_t CS_stop_container(ocre_container_t *container, ocre_container_runtime_cb callback); - -/** - * @brief Destroy a container. - * - * This function removes and destroys the specified container from the runtime. - * - * @param container_id The ID of the container to be destroyed. - * @param callback Callback function to be invoked after destroying the container. - * @return ocre_container_status_t Status of the container destruction. - */ -ocre_container_status_t CS_destroy_container(ocre_container_t *container, ocre_container_runtime_cb callback); - -/** - * @brief Restart a container. - * - * This function restarts a container by stopping and then running it again. - * - * @param container_id The ID of the container to be restarted. - * @param callback Callback function to be invoked after restarting the container. - * @return ocre_container_status_t Status of the container restart. - */ -ocre_container_status_t CS_restart_container(ocre_container_t *container, ocre_container_runtime_cb callback); - -/** - * @brief context initialization - * - * This function initialize the container runtime context. - * - * @param ctx Pointer to the container runtime context. - * @return POSIX style return if the container runtime context was initialized right 0 else -n - */ -int CS_ctx_init(ocre_cs_ctx *ctx); - -#endif // OCRE_CS_SM_IMPL_H diff --git a/src/ocre/components/container_supervisor/message_types.h b/src/ocre/components/container_supervisor/message_types.h deleted file mode 100644 index 8a7f1e75..00000000 --- a/src/ocre/components/container_supervisor/message_types.h +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef OCRE_CS_MESSAGING_TYPES_H -#define OCRE_CS_MESSAGING_TYPES_H - -#include "ocre_core_external.h" - -struct install { - char name[OCRE_MODULE_NAME_LEN]; // +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ocre.h" +#include "context.h" +#include "container.h" +#include "util/string_array.h" + +LOG_MODULE_REGISTER(container); + +struct ocre_container { + char *id; + char *image; + const struct ocre_runtime_vtable *runtime; + bool detached; + ocre_container_status_t status; + pthread_mutex_t mutex; + pthread_cond_t cond; + void *runtime_context; + pthread_t thread; + pthread_attr_t attr; + struct thread_info *tinfo; + char **argv; + char **envp; + int exit_code; +}; + +struct container_thread_params { + int (*func)(void *); + struct ocre_container *container; +}; + +static void *container_thread(void *arg) +{ + int rc; + struct container_thread_params *params = arg; + struct ocre_container *container = params->container; + int (*func)(void *) = params->func; + + free(params); + + /* Run the container */ + + int result = func(container->runtime_context); + + /* Exited */ + + rc = pthread_mutex_lock(&container->mutex); + if (rc) { + LOG_ERR("Failed to lock mutex: rc=%d", rc); + return NULL; + } + + /* Here is the **only** place where we should set the status to exited */ + + container->status = OCRE_CONTAINER_STATUS_EXITED; + container->exit_code = result; + + LOG_INF("Container '%s' exited. Result is = %d", container->id, result); + + /* Notify any waiting threads */ + + rc = pthread_cond_broadcast(&container->cond); + if (rc) { + LOG_WRN("Failed to broadcast conditional variable: rc=%d", rc); + } + + rc = pthread_mutex_unlock(&container->mutex); + if (rc) { + LOG_ERR("Failed to unlock mutex: rc=%d", rc); + return NULL; + } + + /* Cast result int to void pointer so we can return it from the thread */ + + return (void *)(intptr_t)result; +} + +static ocre_container_status_t ocre_container_status_locked(struct ocre_container *container) +{ + if (!container) { + LOG_ERR("Invalid container parameter"); + return OCRE_CONTAINER_STATUS_UNKNOWN; + } + + if (container->status == OCRE_CONTAINER_STATUS_EXITED) { + /* Need to join the thread to clean up resources and get exit status. + * pthread_join should not block here because the thread already exited. + * Here is the only place where we should call pthread_join. + * + * If we later have pthread_join somewhere else, we should not have it here. + */ + + int rc = pthread_join(container->thread, NULL); + if (rc) { + LOG_ERR("Failed to join thread: rc=%d", rc); + return OCRE_CONTAINER_STATUS_UNKNOWN; + } + + /* It looks like we should keep the attr available for the whole life of the thread */ + + rc = pthread_attr_destroy(&container->attr); + if (rc) { + LOG_ERR("Failed to destroy thread attributes: rc=%d", rc); + } + + /* Now the container is really stopped */ + + container->status = OCRE_CONTAINER_STATUS_STOPPED; + } + + return container->status; +} + +struct ocre_container *ocre_container_create(const char *path, const char *runtime, const char *container_id, + bool detached, const struct ocre_container_args *arguments) +{ + int rc; + const char **capabilities = NULL; + const char **mounts = NULL; + + if (!runtime) { + LOG_ERR("Runtime is required"); + return NULL; + } + + struct ocre_container *container = malloc(sizeof(struct ocre_container)); + + if (!container) { + LOG_ERR("Failed to allocate memory: errno=%d", errno); + return NULL; + } + + memset(container, 0, sizeof(struct ocre_container)); + + /* Strip the image name from the path, just to make it look nicer */ + + const char *image = strrchr(path, '/'); + if (image) { + image++; + } else { + image = path; + } + + container->image = strdup(image); + if (!container->image) { + LOG_ERR("Failed to allocate memory for image: errno=%d", errno); + goto error_free; + } + + container->id = strdup(container_id); + if (!container->id) { + LOG_ERR("Failed to allocate memory for id: errno=%d", errno); + goto error_free; + } + + /* Duplicate the arguments */ + + if (arguments) { + capabilities = arguments->capabilities; + mounts = arguments->mounts; + + container->argv = string_array_deep_dup(arguments->argv); + container->envp = string_array_deep_dup(arguments->envp); + + if ((!container->argv && arguments->argv) || (!container->envp && arguments->envp)) { + goto error_free; + } + } + + container->runtime = ocre_get_runtime(runtime); + if (!container->runtime) { + LOG_ERR("Invalid runtime '%s'", runtime); + goto error_free; + } + + rc = pthread_mutex_init(&container->mutex, NULL); + if (rc) { + LOG_ERR("Failed to initialize mutex: rc=%d", rc); + goto error_free; + } + + rc = pthread_cond_init(&container->cond, NULL); + if (rc) { + LOG_ERR("Failed to initialize conditional variable: rc=%d", rc); + goto error_mutex; + } + + container->runtime_context = container->runtime->create( + path, 8192, 8192, capabilities, (const char **)container->argv, (const char **)container->envp, mounts); + if (!container->runtime_context) { + LOG_ERR("Failed to create container"); + goto error_cond; + } + + container->status = OCRE_CONTAINER_STATUS_CREATED; + + container->detached = detached; + + LOG_INF("Created container '%s' with runtime '%s' (path '%s')", container->id, runtime, path); + + return container; + +error_cond: + rc = pthread_cond_destroy(&container->cond); + if (rc) { + LOG_ERR("Failed to deinitialize conditional variable: rc=%d", rc); + } + +error_mutex: + rc = pthread_mutex_destroy(&container->mutex); + if (rc) { + LOG_ERR("Failed to deinitialize mutex: rc=%d", rc); + } + +error_free: + string_array_free(container->argv); + string_array_free(container->envp); + + free(container->image); + free(container->id); + free(container); + + return NULL; +} + +int ocre_container_destroy(struct ocre_container *container) +{ + if (!container) { + LOG_ERR("Invalid arguments"); + return -1; + } + + ocre_container_status_t status = ocre_container_status_locked(container); + if (status != OCRE_CONTAINER_STATUS_STOPPED && status != OCRE_CONTAINER_STATUS_CREATED) { + LOG_ERR("Cannot remove container '%s' because it is in use", container->id); + return -1; + } + + container->runtime->destroy(container->runtime_context); + + int rc; + rc = pthread_mutex_destroy(&container->mutex); + if (rc) { + LOG_ERR("Failed to deinitialize mutex: rc=%d", rc); + } + + rc = pthread_cond_destroy(&container->cond); + if (rc) { + LOG_ERR("Failed to deinitialize conditional variable: rc=%d", rc); + } + + string_array_free(container->argv); + string_array_free(container->envp); + + LOG_INF("Removed container '%s'", container->id); + + free(container->id); + free(container->image); + free(container); + + return 0; +} + +int ocre_container_start(struct ocre_container *container) +{ + if (!container) { + LOG_ERR("Invalid arguments"); + return -1; + } + + int rc; + rc = pthread_mutex_lock(&container->mutex); + if (rc) { + LOG_ERR("Failed to lock mutex: rc=%d", rc); + goto error_status; + } + + ocre_container_status_t status = ocre_container_status_locked(container); + if (status != OCRE_CONTAINER_STATUS_CREATED && status != OCRE_CONTAINER_STATUS_STOPPED) { + LOG_ERR("Container '%s' is not ready to run", container->id); + goto error_mutex; + } + + rc = pthread_attr_init(&container->attr); + if (rc) { + LOG_ERR("Failed to initialize pthread attribute: rc=%d", rc); + goto error_mutex; + } + + // rc = pthread_attr_setstacksize(&container->attr, PTHREAD_STACK_MIN); + // rc = pthread_attr_setstacksize(&container->attr, 8192); + // if (rc) { + // LOG_ERR("Failed to set stack size: rc=%d", rc); + // goto error_attr; + // } + + struct container_thread_params *params; + params = malloc(sizeof(struct container_thread_params)); + if (!params) { + LOG_ERR("Failed to allocate memory (size=%zu) for thread parameters: errno=%d", + sizeof(struct container_thread_params), errno); + goto error_attr; + } + + memset(params, 0, sizeof(struct container_thread_params)); + params->container = container; + params->func = container->runtime->thread_execute; + container->status = OCRE_CONTAINER_STATUS_RUNNING; + + rc = pthread_create(&container->thread, &container->attr, container_thread, params); + if (rc) { + LOG_ERR("Failed to create thread: rc=%d", rc); + goto error_params; + } + + LOG_INF("Started container '%s' on runtime '%s'", container->id, container->runtime->runtime_name); + + rc = pthread_mutex_unlock(&container->mutex); + if (rc) { + LOG_ERR("Failed to unlock mutex: rc=%d", rc); + goto error_status; + } + + if (!container->detached) { + // this will block until the container thread exits + if (ocre_container_wait(container, NULL)) { + LOG_ERR("Failed to wait for container '%s'", container->id); + return -1; + } + } + + return 0; + +error_params: + free(params); + +error_attr: + rc = pthread_attr_destroy(&container->attr); + if (rc) { + LOG_ERR("Failed to destroy thread attributes: rc=%d", rc); + } + +error_mutex: + rc = pthread_mutex_unlock(&container->mutex); + if (rc) { + LOG_ERR("Failed to unlock mutex: rc=%d", rc); + } + +error_status: + LOG_INF("Setting container '%s' status to ERROR", container->id); + container->status = OCRE_CONTAINER_STATUS_ERROR; + + return -1; +} + +ocre_container_status_t ocre_container_get_status(struct ocre_container *container) +{ + if (!container) { + LOG_ERR("Invalid arguments"); + return OCRE_CONTAINER_STATUS_UNKNOWN; + } + + int rc; + rc = pthread_mutex_lock(&container->mutex); + if (rc) { + LOG_ERR("Failed to lock mutex: rc=%d", rc); + return OCRE_CONTAINER_STATUS_UNKNOWN; + } + + ocre_container_status_t status = ocre_container_status_locked(container); + + rc = pthread_mutex_unlock(&container->mutex); + if (rc) { + LOG_ERR("Failed to unlock mutex: rc=%d", rc); + return OCRE_CONTAINER_STATUS_UNKNOWN; + } + + return status; +} + +int ocre_container_kill(struct ocre_container *container) +{ + int ret = -1; + if (!container) { + LOG_ERR("Invalid container"); + return -1; + } + + int rc; + rc = pthread_mutex_lock(&container->mutex); + if (rc) { + LOG_ERR("Failed to lock mutex: rc=%d", rc); + return -1; + } + + if (container->status != OCRE_CONTAINER_STATUS_RUNNING) { + LOG_ERR("Container '%s' is not running", container->id); + goto unlock_mutex; + } + + LOG_INF("Sending kill signal to container '%s'", container->id); + + ret = container->runtime->kill(container->runtime_context); + +unlock_mutex: + rc = pthread_mutex_unlock(&container->mutex); + if (rc) { + LOG_ERR("Failed to unlock mutex: rc=%d", rc); + } + + return ret; +} + +int ocre_container_pause(struct ocre_container *container) +{ + int ret = -1; + if (!container) { + LOG_ERR("Invalid container"); + return -1; + } + + int rc; + rc = pthread_mutex_lock(&container->mutex); + if (rc) { + LOG_ERR("Failed to lock mutex: rc=%d", rc); + return -1; + } + + if (container->status != OCRE_CONTAINER_STATUS_RUNNING) { + LOG_ERR("Container '%s' is not running", container->id); + goto unlock_mutex; + } + + if (!container->runtime->pause) { + LOG_ERR("Container '%s' does not support pause", container->id); + goto unlock_mutex; + } + + LOG_INF("Sending pause signal to container '%s'", container->id); + + ret = container->runtime->pause(container->runtime_context); + +unlock_mutex: + rc = pthread_mutex_unlock(&container->mutex); + if (rc) { + LOG_ERR("Failed to unlock mutex: rc=%d", rc); + } + + return ret; +} + +int ocre_container_unpause(struct ocre_container *container) +{ + int ret = -1; + if (!container) { + LOG_ERR("Invalid container"); + return -1; + } + + int rc; + rc = pthread_mutex_lock(&container->mutex); + if (rc) { + LOG_ERR("Failed to lock mutex: rc=%d", rc); + return -1; + } + + if (container->status != OCRE_CONTAINER_STATUS_PAUSED) { + LOG_ERR("Container '%s' is not paused", container->id); + goto unlock_mutex; + } + + if (!container->runtime->unpause) { + LOG_ERR("Container '%s' does not support unpause", container->id); + goto unlock_mutex; + } + + LOG_INF("Sending unpause signal to container '%s'", container->id); + + ret = container->runtime->unpause(container->runtime_context); + +unlock_mutex: + rc = pthread_mutex_unlock(&container->mutex); + if (rc) { + LOG_ERR("Failed to unlock mutex: rc=%d", rc); + } + + return ret; +} + +int ocre_container_wait(struct ocre_container *container, int *status) +{ + int ret = -1; + + if (!container) { + LOG_ERR("Invalid container"); + return -1; + } + + int rc; + rc = pthread_mutex_lock(&container->mutex); + if (rc) { + LOG_ERR("Failed to lock mutex: rc=%d", rc); + return -1; + } + + if (container->status == OCRE_CONTAINER_STATUS_UNKNOWN || container->status == OCRE_CONTAINER_STATUS_CREATED) { + ret = -1; + goto unlock_mutex; + } + + if (container->status == OCRE_CONTAINER_STATUS_RUNNING) { + LOG_INF("Container '%s' is running", container->id); + rc = pthread_cond_wait(&container->cond, &container->mutex); + if (rc) { + LOG_ERR("Failed to wait on conditional variable: rc=%d", rc); + goto unlock_mutex; + } + } + + ret = 0; + + if (container->status == OCRE_CONTAINER_STATUS_EXITED) { + LOG_INF("Container '%s' was exited", container->id); + if (ocre_container_status_locked(container) != OCRE_CONTAINER_STATUS_STOPPED) { + LOG_ERR("Container '%s' status did not go drom exitted to stopped", container->id); + goto unlock_mutex; + } + } + + if (container->status == OCRE_CONTAINER_STATUS_STOPPED) { + LOG_INF("Container '%s' was stopped", container->id); + ret = 0; + if (status) { + *status = container->exit_code; + } + } + +unlock_mutex: + rc = pthread_mutex_unlock(&container->mutex); + if (rc) { + LOG_ERR("Failed to unlock mutex: rc=%d", rc); + } + + return ret; +} + +char *ocre_container_get_id_a(const struct ocre_container *container) +{ + if (!container) { + LOG_ERR("Invalid container or id"); + return NULL; + } + + return strdup(container->id); +} + +char *ocre_container_get_image_a(const struct ocre_container *container) +{ + if (!container) { + LOG_ERR("Invalid container or id"); + return NULL; + } + + return strdup(container->image); +} + +int ocre_container_id_compare(const struct ocre_container *container, const char *id) +{ + if (!container || !id) { + LOG_ERR("Invalid container or id"); + return -1; + } + + return strcmp(container->id, id); +} diff --git a/src/ocre/container.h b/src/ocre/container.h new file mode 100644 index 00000000..7c16fd57 --- /dev/null +++ b/src/ocre/container.h @@ -0,0 +1,8 @@ +#include + +struct ocre_container; + +struct ocre_container *ocre_container_create(const char *path, const char *runtime, const char *container_id, + bool detached, const struct ocre_container_args *arguments); +int ocre_container_destroy(struct ocre_container *container); +int ocre_container_id_compare(const struct ocre_container *container, const char *id); diff --git a/src/ocre/context.c b/src/ocre/context.c new file mode 100644 index 00000000..c6ca26b8 --- /dev/null +++ b/src/ocre/context.c @@ -0,0 +1,335 @@ +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "container.h" +#include "unique_random_id.h" + +#define RANDOM_ID_LEN 8 + +LOG_MODULE_REGISTER(context); + +struct ocre_context { + pthread_mutex_t mutex; + char *working_directory; + struct container_node *containers; +}; + +struct container_node { + struct ocre_container *container; + struct container_node *next; /* needed for singly- or doubly-linked lists */ +}; + +struct ocre_context *ocre_create_context(const char *workdir) +{ + int rc; + + if (!workdir) { + workdir = CONFIG_OCRE_DEFAULT_WORKING_DIRECTORY; + LOG_INF("Using default working directory: %s", workdir); + } + + struct ocre_context *context = malloc(sizeof(struct ocre_context)); + if (!context) { + LOG_ERR("Failed to allocate memory for context: errno=%d", errno); + return NULL; + } + + memset(context, 0, sizeof(struct ocre_context)); + + /* Initialize working directory */ + + context->working_directory = strdup(workdir); + if (!context->working_directory) { + LOG_ERR("Failed to allocate memory for working directory: errno=%d", errno); + free(context); + goto error_context; + } + + rc = pthread_mutex_init(&context->mutex, NULL); + if (rc) { + LOG_ERR("Failed to initialize context mutex: rc=%d", rc); + goto error_workdir; + } + + /* Initialize containers list */ + + context->containers = NULL; + + return context; + +error_workdir: + free(context->working_directory); + +error_context: + free(context); + + return NULL; +}; + +void ocre_destroy_context(struct ocre_context *context) +{ + pthread_mutex_destroy(&context->mutex); + free(context->working_directory); + free(context); +} + +struct ocre_container *ocre_context_get_container_by_id_locked(const struct ocre_context *context, const char *id) +{ + struct container_node *node; + + LL_FOREACH(context->containers, node) + { + if (!ocre_container_id_compare(node->container, id)) { + return node->container; + } + } + + return NULL; +} + +void ocre_context_destroy(struct ocre_context *context) +{ + struct container_node *node; + + if (!context) { + LOG_ERR("Invalid context"); + return; + } + + /* Send kill event to all containers */ + + LL_FOREACH(context->containers, node) + { + ocre_container_kill(node->container); + } + + /* Wait for all containers to exit */ + + LL_FOREACH(context->containers, node) + { + ocre_container_wait(node->container, NULL); + } + + int rc; + rc = pthread_mutex_destroy(&context->mutex); + if (rc) { + LOG_ERR("Failed to destroy context mutex: rc=%d", rc); + } + + free(context->working_directory); + + free(context); +}; + +struct ocre_container *ocre_context_create_container(struct ocre_context *context, const char *image, + const char *const runtime, const char *container_id, bool detached, + const struct ocre_container_args *arguments) +{ + const char *computed_container_id = NULL; + struct ocre_container *container = NULL; + int rc; + + rc = pthread_mutex_lock(&context->mutex); + if (rc) { + LOG_ERR("Failed to lock context mutex: rc=%d", rc); + return NULL; + } + + /* If no container ID is provided, generate a random one */ + + if (!container_id) { + char random_id[RANDOM_ID_LEN]; + if (make_unique_random_container_id(context, random_id, RANDOM_ID_LEN)) { + LOG_ERR("Failed to generate random container ID"); + goto unlock_mutex; + } + + computed_container_id = random_id; + } else if (ocre_context_get_container_by_id_locked(context, container_id)) { + LOG_ERR("Container with ID '%s' already exists", container_id); + goto unlock_mutex; + } else { + computed_container_id = container_id; + } + + /* Build the absolute path to the image */ + + char *abs_path = malloc(strlen(context->working_directory) + strlen("/images/") + strlen(image) + 1); + if (!abs_path) { + LOG_ERR("Failed to allocate memory for absolute path"); + goto unlock_mutex; + } + + strcpy(abs_path, context->working_directory); + strcat(abs_path, "/images/"); + strcat(abs_path, image); + + /* Create the container */ + + container = ocre_container_create(abs_path, runtime, computed_container_id, detached, arguments); + if (!container) { + LOG_ERR("Failed to create container %s: errno=%d", computed_container_id, errno); + goto free_path; + } + + /* Add the container to the context */ + + struct container_node *node = malloc(sizeof(struct container_node)); + if (!node) { + LOG_ERR("Failed to allocate memory for container node"); + goto error_container; + } + + node->container = container; + + LL_APPEND(context->containers, node); + + goto free_path; + +error_container: + ocre_container_destroy(container); + +free_path: + free(abs_path); + +unlock_mutex: + rc = pthread_mutex_unlock(&context->mutex); + if (rc) { + LOG_ERR("Failed to unlock context mutex: rc=%d", rc); + return NULL; + } + + return container; +} + +int ocre_context_remove_container(struct ocre_context *context, struct ocre_container *container) +{ + struct container_node *node = NULL; + + if (!context || !container) { + LOG_ERR("Invalid arguments"); + return -1; + } + + LL_FOREACH(context->containers, node) + { + if (node->container == container) { + int rc = ocre_container_destroy(container); + if (rc) { + LOG_ERR("Failed to destroy container: rc=%d", rc); + return rc; + } + + LL_DELETE(context->containers, node); + free(node); + + return 0; + } + } + + return -1; +} + +int ocre_context_get_num_containers(struct ocre_context *context) +{ + int rc; + int count = 0; + struct container_node *node = NULL; + + if (!context) { + LOG_ERR("Invalid context"); + return -1; + } + + rc = pthread_mutex_lock(&context->mutex); + if (rc) { + LOG_ERR("Failed to lock context mutex: rc=%d", rc); + return -1; + } + + LL_COUNT(context->containers, node, count); + + rc = pthread_mutex_unlock(&context->mutex); + if (rc) { + LOG_ERR("Failed to unlock context mutex: rc=%d", rc); + return -1; + } + + return count; +} + +char *ocre_context_get_working_directory(struct ocre_context *context) { + /* We never change this, no need to lock */ + + return context->working_directory; +} + +int ocre_context_list_containers(struct ocre_context *context, struct ocre_container **containers, int max_size) +{ + int rc; + int count = 0; + struct container_node *node = NULL; + + if (!context || !containers) { + LOG_ERR("Invalid arguments"); + return -1; + } + + rc = pthread_mutex_lock(&context->mutex); + if (rc) { + LOG_ERR("Failed to lock context mutex: rc=%d", rc); + return -1; + } + + LL_FOREACH(context->containers, node) + { + if (count >= max_size) { + break; + } + + containers[count++] = node->container; + } + + rc = pthread_mutex_unlock(&context->mutex); + if (rc) { + LOG_ERR("Failed to unlock context mutex: rc=%d", rc); + return -1; + } + + return count; +} + +struct ocre_container *ocre_context_get_container_by_id(struct ocre_context *context, const char *id) +{ + int rc; + + if (!context || !id) { + LOG_ERR("Invalid arguments"); + return NULL; + } + + rc = pthread_mutex_lock(&context->mutex); + if (rc) { + LOG_ERR("Failed to lock context mutex: rc=%d", rc); + return NULL; + } + + struct ocre_container *ret = ocre_context_get_container_by_id_locked(context, id); + + rc = pthread_mutex_unlock(&context->mutex); + if (rc) { + LOG_ERR("Failed to unlock context mutex: rc=%d", rc); + return NULL; + } + + return ret; +} diff --git a/src/ocre/context.h b/src/ocre/context.h new file mode 100644 index 00000000..1f959c0c --- /dev/null +++ b/src/ocre/context.h @@ -0,0 +1,6 @@ +struct ocre_context; + +// struct ocre_container *ocre_container_create(const char *path, const char *const runtime, const char *container_id, +// const void *arguments); +// void ocre_container_destroy(struct ocre_container *container); +struct ocre_container *ocre_context_get_container_by_id_locked(const struct ocre_context *context, const char *id); diff --git a/src/ocre/include/ocre/ocre.h b/src/ocre/include/ocre/ocre.h new file mode 100644 index 00000000..abd745ab --- /dev/null +++ b/src/ocre/include/ocre/ocre.h @@ -0,0 +1,81 @@ +#ifndef OCRE_H +#define OCRE_H + +#include +#include + +#include + +/** + * @brief Enum representing the possible status of a container. + */ +typedef enum { + OCRE_CONTAINER_STATUS_UNKNOWN = 0, ///< Status is unknown. + OCRE_CONTAINER_STATUS_CREATED, ///< Container has been created. + OCRE_CONTAINER_STATUS_RUNNING, ///< Container is currently running. + OCRE_CONTAINER_STATUS_PAUSED, ///< Container is currently paused. + OCRE_CONTAINER_STATUS_EXITED, ///< Container has exited but we did not get the exit code yet. + OCRE_CONTAINER_STATUS_STOPPED, ///< Container has been stopped. + OCRE_CONTAINER_STATUS_ERROR, ///< An error occurred with the container. +} ocre_container_status_t; + +struct ocre_config { + const char *version; + const char *commit_id; + const char *build_info; +}; + +extern const struct ocre_config ocre_build_configuration; + +struct ocre_context; + +// struct ocre_context_status { +// int num_containers; +// int num_running_containers; +// char *ocre_workdir; +// }; + +struct ocre_container_args { + const char **argv; + const char **envp; + const char **capabilities; + const char **mounts; +}; + +// struct ocre_container_info { +// const char *id; +// const char *image; +// struct ocre_container_args args; +// int exit_code; +// }; + +struct ocre_container; + +int ocre_initialize(void); +int ocre_initialize_with_runtimes(const struct ocre_runtime_vtable *const vtable[]); +struct ocre_context *ocre_create_context(const char *workdir); +void ocre_destroy_context(struct ocre_context *context); +void ocre_deinitialize(void); + +// int ocre_context_get_status(const struct ocre_context_status *status); +struct ocre_container *ocre_context_create_container(struct ocre_context *context, const char *image, + const char *const runtime, const char *container_id, bool detached, + const struct ocre_container_args *arguments); +struct ocre_container *ocre_context_get_container_by_id(struct ocre_context *context, const char *id); +int ocre_context_remove_container(struct ocre_context *context, struct ocre_container *container); +int ocre_context_get_num_containers(struct ocre_context *context); +int ocre_context_list_containers(struct ocre_context *context, struct ocre_container **containers, int max_size); +char *ocre_context_get_working_directory(struct ocre_context *context); + +int ocre_container_start(struct ocre_container *container); +ocre_container_status_t ocre_container_get_status(struct ocre_container *container); +char *ocre_container_get_id_a(const struct ocre_container *container); +char *ocre_container_get_image_a(const struct ocre_container *container); +// int ocre_container_get_info(struct ocre_container *container, struct container_info *info); +int ocre_container_pause(struct ocre_container *container); +int ocre_container_unpause(struct ocre_container *container); +// int ocre_container_stop(struct ocre_container *container); +int ocre_container_kill(struct ocre_container *container); +int ocre_container_wait(struct ocre_container *container, int *status); + +#endif /* OCRE_H */ diff --git a/src/ocre/include/uthash/utarray.h b/src/ocre/include/uthash/utarray.h new file mode 100644 index 00000000..16760f9d --- /dev/null +++ b/src/ocre/include/uthash/utarray.h @@ -0,0 +1,258 @@ +/* +Copyright (c) 2008-2025, Troy D. Hanson https://troydhanson.github.io/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* a dynamic array implementation using macros + */ +#ifndef UTARRAY_H +#define UTARRAY_H + +#define UTARRAY_VERSION 2.3.0 + +#include /* size_t */ +#include /* memset, etc */ +#include /* exit */ + +#ifdef __GNUC__ +#define UTARRAY_UNUSED __attribute__((__unused__)) +#else +#define UTARRAY_UNUSED +#endif + +#ifndef utarray_oom +#define utarray_oom() exit(-1) +#endif + +typedef void (ctor_f)(void *dst, const void *src); +typedef void (dtor_f)(void *elt); +typedef void (init_f)(void *elt); +typedef struct { + size_t sz; + init_f *init; + ctor_f *copy; + dtor_f *dtor; +} UT_icd; + +typedef struct { + unsigned i,n;/* i: index of next available slot, n: num slots */ + UT_icd icd; /* initializer, copy and destructor functions */ + char *d; /* n slots of size icd->sz*/ +} UT_array; + +#define utarray_init(a,_icd) do { \ + memset(a,0,sizeof(UT_array)); \ + (a)->icd = *(_icd); \ +} while(0) + +#define utarray_done(a) do { \ + if ((a)->n) { \ + if ((a)->icd.dtor) { \ + unsigned _ut_i; \ + for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \ + (a)->icd.dtor(utarray_eltptr(a,_ut_i)); \ + } \ + } \ + free((a)->d); \ + } \ + (a)->n=0; \ +} while(0) + +#define utarray_new(a,_icd) do { \ + (a) = (UT_array*)malloc(sizeof(UT_array)); \ + if ((a) == NULL) { \ + utarray_oom(); \ + } \ + utarray_init(a,_icd); \ +} while(0) + +#define utarray_free(a) do { \ + utarray_done(a); \ + free(a); \ +} while(0) + +#define utarray_reserve(a,by) do { \ + if (((a)->i+(by)) > (a)->n) { \ + char *utarray_tmp; \ + while (((a)->i+(by)) > (a)->n) { (a)->n = ((a)->n ? (2*(a)->n) : 8); } \ + utarray_tmp=(char*)realloc((a)->d, (a)->n*(a)->icd.sz); \ + if (utarray_tmp == NULL) { \ + utarray_oom(); \ + } \ + (a)->d=utarray_tmp; \ + } \ +} while(0) + +#define utarray_push_back(a,p) do { \ + utarray_reserve(a,1); \ + if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,(a)->i++), p); } \ + else { memcpy(_utarray_eltptr(a,(a)->i++), p, (a)->icd.sz); }; \ +} while(0) + +#define utarray_pop_back(a) do { \ + if ((a)->icd.dtor) { (a)->icd.dtor( _utarray_eltptr(a,--((a)->i))); } \ + else { (a)->i--; } \ +} while(0) + +#define utarray_extend_back(a) do { \ + utarray_reserve(a,1); \ + if ((a)->icd.init) { (a)->icd.init(_utarray_eltptr(a,(a)->i)); } \ + else { memset(_utarray_eltptr(a,(a)->i),0,(a)->icd.sz); } \ + (a)->i++; \ +} while(0) + +#define utarray_len(a) ((a)->i) + +#define utarray_eltptr(a,j) (((j) < (a)->i) ? _utarray_eltptr(a,j) : NULL) +#define _utarray_eltptr(a,j) ((void*)((a)->d + ((a)->icd.sz * (j)))) + +#define utarray_insert(a,p,j) do { \ + if ((j) > (a)->i) utarray_resize(a,j); \ + utarray_reserve(a,1); \ + if ((j) < (a)->i) { \ + memmove( _utarray_eltptr(a,(j)+1), _utarray_eltptr(a,j), \ + ((a)->i - (j))*((a)->icd.sz)); \ + } \ + if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,j), p); } \ + else { memcpy(_utarray_eltptr(a,j), p, (a)->icd.sz); }; \ + (a)->i++; \ +} while(0) + +#define utarray_replace(a,p,j) do { \ + if ((a)->icd.dtor) { (a)->icd.dtor(_utarray_eltptr(a,j)); } \ + if ((a)->icd.copy) { (a)->icd.copy(_utarray_eltptr(a,j), p); } \ + else { memcpy(_utarray_eltptr(a,j), p, (a)->icd.sz); } \ +} while(0) + +#define utarray_inserta(a,w,j) do { \ + if (utarray_len(w) == 0) break; \ + if ((j) > (a)->i) utarray_resize(a,j); \ + utarray_reserve(a,utarray_len(w)); \ + if ((j) < (a)->i) { \ + memmove(_utarray_eltptr(a,(j)+utarray_len(w)), \ + _utarray_eltptr(a,j), \ + ((a)->i - (j))*((a)->icd.sz)); \ + } \ + if ((a)->icd.copy) { \ + unsigned _ut_i; \ + for(_ut_i=0;_ut_i<(w)->i;_ut_i++) { \ + (a)->icd.copy(_utarray_eltptr(a, (j) + _ut_i), _utarray_eltptr(w, _ut_i)); \ + } \ + } else { \ + memcpy(_utarray_eltptr(a,j), _utarray_eltptr(w,0), \ + utarray_len(w)*((a)->icd.sz)); \ + } \ + (a)->i += utarray_len(w); \ +} while(0) + +#define utarray_resize(dst,num) do { \ + unsigned _ut_i; \ + if ((dst)->i > (unsigned)(num)) { \ + if ((dst)->icd.dtor) { \ + for (_ut_i = (num); _ut_i < (dst)->i; ++_ut_i) { \ + (dst)->icd.dtor(_utarray_eltptr(dst, _ut_i)); \ + } \ + } \ + } else if ((dst)->i < (unsigned)(num)) { \ + utarray_reserve(dst, (num) - (dst)->i); \ + if ((dst)->icd.init) { \ + for (_ut_i = (dst)->i; _ut_i < (unsigned)(num); ++_ut_i) { \ + (dst)->icd.init(_utarray_eltptr(dst, _ut_i)); \ + } \ + } else { \ + memset(_utarray_eltptr(dst, (dst)->i), 0, (dst)->icd.sz*((num) - (dst)->i)); \ + } \ + } \ + (dst)->i = (num); \ +} while(0) + +#define utarray_concat(dst,src) do { \ + utarray_inserta(dst, src, utarray_len(dst)); \ +} while(0) + +#define utarray_erase(a,pos,len) do { \ + if ((a)->icd.dtor) { \ + unsigned _ut_i; \ + for (_ut_i = 0; _ut_i < (len); _ut_i++) { \ + (a)->icd.dtor(utarray_eltptr(a, (pos) + _ut_i)); \ + } \ + } \ + if ((a)->i > ((pos) + (len))) { \ + memmove(_utarray_eltptr(a, pos), _utarray_eltptr(a, (pos) + (len)), \ + ((a)->i - ((pos) + (len))) * (a)->icd.sz); \ + } \ + (a)->i -= (len); \ +} while(0) + +#define utarray_renew(a,u) do { \ + if (a) utarray_clear(a); \ + else utarray_new(a, u); \ +} while(0) + +#define utarray_clear(a) do { \ + if ((a)->i > 0) { \ + if ((a)->icd.dtor) { \ + unsigned _ut_i; \ + for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \ + (a)->icd.dtor(_utarray_eltptr(a, _ut_i)); \ + } \ + } \ + (a)->i = 0; \ + } \ +} while(0) + +#define utarray_sort(a,cmp) do { \ + qsort((a)->d, (a)->i, (a)->icd.sz, cmp); \ +} while(0) + +#define utarray_find(a,v,cmp) bsearch((v),(a)->d,(a)->i,(a)->icd.sz,cmp) + +#define utarray_front(a) (((a)->i) ? (_utarray_eltptr(a,0)) : NULL) +#define utarray_next(a,e) (((e)==NULL) ? utarray_front(a) : (((a)->i != utarray_eltidx(a,e)+1) ? _utarray_eltptr(a,utarray_eltidx(a,e)+1) : NULL)) +#define utarray_prev(a,e) (((e)==NULL) ? utarray_back(a) : ((utarray_eltidx(a,e) != 0) ? _utarray_eltptr(a,utarray_eltidx(a,e)-1) : NULL)) +#define utarray_back(a) (((a)->i) ? (_utarray_eltptr(a,(a)->i-1)) : NULL) +#define utarray_eltidx(a,e) (((char*)(e) - (a)->d) / (a)->icd.sz) + +/* last we pre-define a few icd for common utarrays of ints and strings */ +static void utarray_str_cpy(void *dst, const void *src) { + char *const *srcc = (char *const *)src; + char **dstc = (char**)dst; + if (*srcc == NULL) { + *dstc = NULL; + } else { + *dstc = (char*)malloc(strlen(*srcc) + 1); + if (*dstc == NULL) { + utarray_oom(); + } else { + strcpy(*dstc, *srcc); + } + } +} +static void utarray_str_dtor(void *elt) { + char **eltc = (char**)elt; + if (*eltc != NULL) free(*eltc); +} +static const UT_icd ut_str_icd UTARRAY_UNUSED = {sizeof(char*),NULL,utarray_str_cpy,utarray_str_dtor}; +static const UT_icd ut_int_icd UTARRAY_UNUSED = {sizeof(int),NULL,NULL,NULL}; +static const UT_icd ut_ptr_icd UTARRAY_UNUSED = {sizeof(void*),NULL,NULL,NULL}; + + +#endif /* UTARRAY_H */ diff --git a/src/ocre/include/uthash/uthash.h b/src/ocre/include/uthash/uthash.h new file mode 100644 index 00000000..06c2eebd --- /dev/null +++ b/src/ocre/include/uthash/uthash.h @@ -0,0 +1,1137 @@ +/* +Copyright (c) 2003-2025, Troy D. Hanson https://troydhanson.github.io/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef UTHASH_H +#define UTHASH_H + +#define UTHASH_VERSION 2.3.0 + +#include /* memcmp, memset, strlen */ +#include /* ptrdiff_t */ +#include /* exit */ + +#if defined(HASH_NO_STDINT) && HASH_NO_STDINT +/* The user doesn't have , and must figure out their own way + to provide definitions for uint8_t and uint32_t. */ +#else +#include /* uint8_t, uint32_t */ +#endif + +/* These macros use decltype or the earlier __typeof GNU extension. + As decltype is only available in newer compilers (VS2010 or gcc 4.3+ + when compiling c++ source) this code uses whatever method is needed + or, for VS2008 where neither is available, uses casting workarounds. */ +#if !defined(DECLTYPE) && !defined(NO_DECLTYPE) +#if defined(_MSC_VER) /* MS compiler */ +#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ +#define DECLTYPE(x) (decltype(x)) +#else /* VS2008 or older (or VS2010 in C mode) */ +#define NO_DECLTYPE +#endif +#elif defined(__MCST__) /* Elbrus C Compiler */ +#define DECLTYPE(x) (__typeof(x)) +#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__) +#define NO_DECLTYPE +#else /* GNU, Sun and other compilers */ +#define DECLTYPE(x) (__typeof(x)) +#endif +#endif + +#ifdef NO_DECLTYPE +#define DECLTYPE(x) +#define DECLTYPE_ASSIGN(dst,src) \ +do { \ + char **_da_dst = (char**)(&(dst)); \ + *_da_dst = (char*)(src); \ +} while (0) +#else +#define DECLTYPE_ASSIGN(dst,src) \ +do { \ + (dst) = DECLTYPE(dst)(src); \ +} while (0) +#endif + +#ifndef uthash_malloc +#define uthash_malloc(sz) malloc(sz) /* malloc fcn */ +#endif +#ifndef uthash_free +#define uthash_free(ptr,sz) free(ptr) /* free fcn */ +#endif +#ifndef uthash_bzero +#define uthash_bzero(a,n) memset(a,'\0',n) +#endif +#ifndef uthash_strlen +#define uthash_strlen(s) strlen(s) +#endif + +#ifndef HASH_FUNCTION +#define HASH_FUNCTION(keyptr,keylen,hashv) HASH_JEN(keyptr, keylen, hashv) +#endif + +#ifndef HASH_KEYCMP +#define HASH_KEYCMP(a,b,n) memcmp(a,b,n) +#endif + +#ifndef uthash_noexpand_fyi +#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ +#endif +#ifndef uthash_expand_fyi +#define uthash_expand_fyi(tbl) /* can be defined to log expands */ +#endif + +#ifndef HASH_NONFATAL_OOM +#define HASH_NONFATAL_OOM 0 +#endif + +#if HASH_NONFATAL_OOM +/* malloc failures can be recovered from */ + +#ifndef uthash_nonfatal_oom +#define uthash_nonfatal_oom(obj) do {} while (0) /* non-fatal OOM error */ +#endif + +#define HASH_RECORD_OOM(oomed) do { (oomed) = 1; } while (0) +#define IF_HASH_NONFATAL_OOM(x) x + +#else +/* malloc failures result in lost memory, hash tables are unusable */ + +#ifndef uthash_fatal +#define uthash_fatal(msg) exit(-1) /* fatal OOM error */ +#endif + +#define HASH_RECORD_OOM(oomed) uthash_fatal("out of memory") +#define IF_HASH_NONFATAL_OOM(x) + +#endif + +/* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS 32U /* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS_LOG2 5U /* lg2 of initial number of buckets */ +#define HASH_BKT_CAPACITY_THRESH 10U /* expand when bucket count reaches */ + +/* calculate the element whose hash handle address is hhp */ +#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho))) +/* calculate the hash handle from element address elp */ +#define HH_FROM_ELMT(tbl,elp) ((UT_hash_handle*)(void*)(((char*)(elp)) + ((tbl)->hho))) + +#define HASH_ROLLBACK_BKT(hh, head, itemptrhh) \ +do { \ + struct UT_hash_handle *_hd_hh_item = (itemptrhh); \ + unsigned _hd_bkt; \ + HASH_TO_BKT(_hd_hh_item->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ + (head)->hh.tbl->buckets[_hd_bkt].count++; \ + _hd_hh_item->hh_next = NULL; \ + _hd_hh_item->hh_prev = NULL; \ +} while (0) + +#define HASH_VALUE(keyptr,keylen,hashv) \ +do { \ + HASH_FUNCTION(keyptr, keylen, hashv); \ +} while (0) + +#define HASH_FIND_BYHASHVALUE(hh,head,keyptr,keylen,hashval,out) \ +do { \ + (out) = NULL; \ + if (head) { \ + unsigned _hf_bkt; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _hf_bkt); \ + if (HASH_BLOOM_TEST((head)->hh.tbl, hashval)) { \ + HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], keyptr, keylen, hashval, out); \ + } \ + } \ +} while (0) + +#define HASH_FIND(hh,head,keyptr,keylen,out) \ +do { \ + (out) = NULL; \ + if (head) { \ + unsigned _hf_hashv; \ + HASH_VALUE(keyptr, keylen, _hf_hashv); \ + HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, out); \ + } \ +} while (0) + +#ifdef HASH_BLOOM +#define HASH_BLOOM_BITLEN (1UL << HASH_BLOOM) +#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8UL) + (((HASH_BLOOM_BITLEN%8UL)!=0UL) ? 1UL : 0UL) +#define HASH_BLOOM_MAKE(tbl,oomed) \ +do { \ + (tbl)->bloom_nbits = HASH_BLOOM; \ + (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \ + if (!(tbl)->bloom_bv) { \ + HASH_RECORD_OOM(oomed); \ + } else { \ + uthash_bzero((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ + (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ + } \ +} while (0) + +#define HASH_BLOOM_FREE(tbl) \ +do { \ + uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ +} while (0) + +#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8U] |= (1U << ((idx)%8U))) +#define HASH_BLOOM_BITTEST(bv,idx) ((bv[(idx)/8U] & (1U << ((idx)%8U))) != 0) + +#define HASH_BLOOM_ADD(tbl,hashv) \ + HASH_BLOOM_BITSET((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U))) + +#define HASH_BLOOM_TEST(tbl,hashv) \ + HASH_BLOOM_BITTEST((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U))) + +#else +#define HASH_BLOOM_MAKE(tbl,oomed) +#define HASH_BLOOM_FREE(tbl) +#define HASH_BLOOM_ADD(tbl,hashv) +#define HASH_BLOOM_TEST(tbl,hashv) 1 +#define HASH_BLOOM_BYTELEN 0U +#endif + +#define HASH_MAKE_TABLE(hh,head,oomed) \ +do { \ + (head)->hh.tbl = (UT_hash_table*)uthash_malloc(sizeof(UT_hash_table)); \ + if (!(head)->hh.tbl) { \ + HASH_RECORD_OOM(oomed); \ + } else { \ + uthash_bzero((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head)->hh.tbl->tail = &((head)->hh); \ + (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ + (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ + (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \ + (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \ + HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \ + (head)->hh.tbl->signature = HASH_SIGNATURE; \ + if (!(head)->hh.tbl->buckets) { \ + HASH_RECORD_OOM(oomed); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + } else { \ + uthash_bzero((head)->hh.tbl->buckets, \ + HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \ + HASH_BLOOM_MAKE((head)->hh.tbl, oomed); \ + IF_HASH_NONFATAL_OOM( \ + if (oomed) { \ + uthash_free((head)->hh.tbl->buckets, \ + HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + } \ + ) \ + } \ + } \ +} while (0) + +#define HASH_REPLACE_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,replaced,cmpfcn) \ +do { \ + (replaced) = NULL; \ + HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ + if (replaced) { \ + HASH_DELETE(hh, head, replaced); \ + } \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn); \ +} while (0) + +#define HASH_REPLACE_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add,replaced) \ +do { \ + (replaced) = NULL; \ + HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ + if (replaced) { \ + HASH_DELETE(hh, head, replaced); \ + } \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add); \ +} while (0) + +#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \ +do { \ + unsigned _hr_hashv; \ + HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ + HASH_REPLACE_BYHASHVALUE(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced); \ +} while (0) + +#define HASH_REPLACE_INORDER(hh,head,fieldname,keylen_in,add,replaced,cmpfcn) \ +do { \ + unsigned _hr_hashv; \ + HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ + HASH_REPLACE_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced, cmpfcn); \ +} while (0) + +#define HASH_APPEND_LIST(hh, head, add) \ +do { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ + (head)->hh.tbl->tail->next = (add); \ + (head)->hh.tbl->tail = &((add)->hh); \ +} while (0) + +#define HASH_AKBI_INNER_LOOP(hh,head,add,cmpfcn) \ +do { \ + do { \ + if (cmpfcn(DECLTYPE(head)(_hs_iter), add) > 0) { \ + break; \ + } \ + } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \ +} while (0) + +#ifdef NO_DECLTYPE +#undef HASH_AKBI_INNER_LOOP +#define HASH_AKBI_INNER_LOOP(hh,head,add,cmpfcn) \ +do { \ + char *_hs_saved_head = (char*)(head); \ + do { \ + DECLTYPE_ASSIGN(head, _hs_iter); \ + if (cmpfcn(head, add) > 0) { \ + DECLTYPE_ASSIGN(head, _hs_saved_head); \ + break; \ + } \ + DECLTYPE_ASSIGN(head, _hs_saved_head); \ + } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \ +} while (0) +#endif + +#if HASH_NONFATAL_OOM + +#define HASH_ADD_TO_TABLE(hh,head,keyptr,keylen_in,hashval,add,oomed) \ +do { \ + if (!(oomed)) { \ + unsigned _ha_bkt; \ + (head)->hh.tbl->num_items++; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ + HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \ + if (oomed) { \ + HASH_ROLLBACK_BKT(hh, head, &(add)->hh); \ + HASH_DELETE_HH(hh, head, &(add)->hh); \ + (add)->hh.tbl = NULL; \ + uthash_nonfatal_oom(add); \ + } else { \ + HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ + HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ + } \ + } else { \ + (add)->hh.tbl = NULL; \ + uthash_nonfatal_oom(add); \ + } \ +} while (0) + +#else + +#define HASH_ADD_TO_TABLE(hh,head,keyptr,keylen_in,hashval,add,oomed) \ +do { \ + unsigned _ha_bkt; \ + (head)->hh.tbl->num_items++; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ + HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \ + HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ + HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ +} while (0) + +#endif + + +#define HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh,head,keyptr,keylen_in,hashval,add,cmpfcn) \ +do { \ + IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \ + (add)->hh.hashv = (hashval); \ + (add)->hh.key = (char*) (keyptr); \ + (add)->hh.keylen = (unsigned) (keylen_in); \ + if (!(head)) { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = NULL; \ + HASH_MAKE_TABLE(hh, add, _ha_oomed); \ + IF_HASH_NONFATAL_OOM( if (!_ha_oomed) { ) \ + (head) = (add); \ + IF_HASH_NONFATAL_OOM( } ) \ + } else { \ + void *_hs_iter = (head); \ + (add)->hh.tbl = (head)->hh.tbl; \ + HASH_AKBI_INNER_LOOP(hh, head, add, cmpfcn); \ + if (_hs_iter) { \ + (add)->hh.next = _hs_iter; \ + if (((add)->hh.prev = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev)) { \ + HH_FROM_ELMT((head)->hh.tbl, (add)->hh.prev)->next = (add); \ + } else { \ + (head) = (add); \ + } \ + HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev = (add); \ + } else { \ + HASH_APPEND_LIST(hh, head, add); \ + } \ + } \ + HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \ + HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE_INORDER"); \ +} while (0) + +#define HASH_ADD_KEYPTR_INORDER(hh,head,keyptr,keylen_in,add,cmpfcn) \ +do { \ + unsigned _hs_hashv; \ + HASH_VALUE(keyptr, keylen_in, _hs_hashv); \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, keyptr, keylen_in, _hs_hashv, add, cmpfcn); \ +} while (0) + +#define HASH_ADD_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,cmpfcn) \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn) + +#define HASH_ADD_INORDER(hh,head,fieldname,keylen_in,add,cmpfcn) \ + HASH_ADD_KEYPTR_INORDER(hh, head, &((add)->fieldname), keylen_in, add, cmpfcn) + +#define HASH_ADD_KEYPTR_BYHASHVALUE(hh,head,keyptr,keylen_in,hashval,add) \ +do { \ + IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \ + (add)->hh.hashv = (hashval); \ + (add)->hh.key = (const void*) (keyptr); \ + (add)->hh.keylen = (unsigned) (keylen_in); \ + if (!(head)) { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = NULL; \ + HASH_MAKE_TABLE(hh, add, _ha_oomed); \ + IF_HASH_NONFATAL_OOM( if (!_ha_oomed) { ) \ + (head) = (add); \ + IF_HASH_NONFATAL_OOM( } ) \ + } else { \ + (add)->hh.tbl = (head)->hh.tbl; \ + HASH_APPEND_LIST(hh, head, add); \ + } \ + HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \ + HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE"); \ +} while (0) + +#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \ +do { \ + unsigned _ha_hashv; \ + HASH_VALUE(keyptr, keylen_in, _ha_hashv); \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, keyptr, keylen_in, _ha_hashv, add); \ +} while (0) + +#define HASH_ADD_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add) \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add) + +#define HASH_ADD(hh,head,fieldname,keylen_in,add) \ + HASH_ADD_KEYPTR(hh, head, &((add)->fieldname), keylen_in, add) + +#define HASH_TO_BKT(hashv,num_bkts,bkt) \ +do { \ + bkt = ((hashv) & ((num_bkts) - 1U)); \ +} while (0) + +/* delete "delptr" from the hash table. + * "the usual" patch-up process for the app-order doubly-linked-list. + * The use of _hd_hh_del below deserves special explanation. + * These used to be expressed using (delptr) but that led to a bug + * if someone used the same symbol for the head and deletee, like + * HASH_DELETE(hh,users,users); + * We want that to work, but by changing the head (users) below + * we were forfeiting our ability to further refer to the deletee (users) + * in the patch-up process. Solution: use scratch space to + * copy the deletee pointer, then the latter references are via that + * scratch pointer rather than through the repointed (users) symbol. + */ +#define HASH_DELETE(hh,head,delptr) \ + HASH_DELETE_HH(hh, head, &(delptr)->hh) + +#define HASH_DELETE_HH(hh,head,delptrhh) \ +do { \ + const struct UT_hash_handle *_hd_hh_del = (delptrhh); \ + if ((_hd_hh_del->prev == NULL) && (_hd_hh_del->next == NULL)) { \ + HASH_BLOOM_FREE((head)->hh.tbl); \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head) = NULL; \ + } else { \ + unsigned _hd_bkt; \ + if (_hd_hh_del == (head)->hh.tbl->tail) { \ + (head)->hh.tbl->tail = HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev); \ + } \ + if (_hd_hh_del->prev != NULL) { \ + HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev)->next = _hd_hh_del->next; \ + } else { \ + DECLTYPE_ASSIGN(head, _hd_hh_del->next); \ + } \ + if (_hd_hh_del->next != NULL) { \ + HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->next)->prev = _hd_hh_del->prev; \ + } \ + HASH_TO_BKT(_hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ + HASH_DEL_IN_BKT((head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ + (head)->hh.tbl->num_items--; \ + } \ + HASH_FSCK(hh, head, "HASH_DELETE_HH"); \ +} while (0) + +/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */ +#define HASH_FIND_STR(head,findstr,out) \ +do { \ + unsigned _uthash_hfstr_keylen = (unsigned)uthash_strlen(findstr); \ + HASH_FIND(hh, head, findstr, _uthash_hfstr_keylen, out); \ +} while (0) +#define HASH_ADD_STR(head,strfield,add) \ +do { \ + unsigned _uthash_hastr_keylen = (unsigned)uthash_strlen((add)->strfield); \ + HASH_ADD(hh, head, strfield[0], _uthash_hastr_keylen, add); \ +} while (0) +#define HASH_REPLACE_STR(head,strfield,add,replaced) \ +do { \ + unsigned _uthash_hrstr_keylen = (unsigned)uthash_strlen((add)->strfield); \ + HASH_REPLACE(hh, head, strfield[0], _uthash_hrstr_keylen, add, replaced); \ +} while (0) +#define HASH_FIND_INT(head,findint,out) \ + HASH_FIND(hh,head,findint,sizeof(int),out) +#define HASH_ADD_INT(head,intfield,add) \ + HASH_ADD(hh,head,intfield,sizeof(int),add) +#define HASH_REPLACE_INT(head,intfield,add,replaced) \ + HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced) +#define HASH_FIND_PTR(head,findptr,out) \ + HASH_FIND(hh,head,findptr,sizeof(void *),out) +#define HASH_ADD_PTR(head,ptrfield,add) \ + HASH_ADD(hh,head,ptrfield,sizeof(void *),add) +#define HASH_REPLACE_PTR(head,ptrfield,add,replaced) \ + HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced) +#define HASH_DEL(head,delptr) \ + HASH_DELETE(hh,head,delptr) + +/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined. + * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined. + */ +#ifdef HASH_DEBUG +#include /* fprintf, stderr */ +#define HASH_OOPS(...) do { fprintf(stderr, __VA_ARGS__); exit(-1); } while (0) +#define HASH_FSCK(hh,head,where) \ +do { \ + struct UT_hash_handle *_thh; \ + if (head) { \ + unsigned _bkt_i; \ + unsigned _count = 0; \ + char *_prev; \ + for (_bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; ++_bkt_i) { \ + unsigned _bkt_count = 0; \ + _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ + _prev = NULL; \ + while (_thh) { \ + if (_prev != (char*)(_thh->hh_prev)) { \ + HASH_OOPS("%s: invalid hh_prev %p, actual %p\n", \ + (where), (void*)_thh->hh_prev, (void*)_prev); \ + } \ + _bkt_count++; \ + _prev = (char*)(_thh); \ + _thh = _thh->hh_next; \ + } \ + _count += _bkt_count; \ + if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \ + HASH_OOPS("%s: invalid bucket count %u, actual %u\n", \ + (where), (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ + } \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("%s: invalid hh item count %u, actual %u\n", \ + (where), (head)->hh.tbl->num_items, _count); \ + } \ + _count = 0; \ + _prev = NULL; \ + _thh = &(head)->hh; \ + while (_thh) { \ + _count++; \ + if (_prev != (char*)_thh->prev) { \ + HASH_OOPS("%s: invalid prev %p, actual %p\n", \ + (where), (void*)_thh->prev, (void*)_prev); \ + } \ + _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \ + _thh = (_thh->next ? HH_FROM_ELMT((head)->hh.tbl, _thh->next) : NULL); \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("%s: invalid app item count %u, actual %u\n", \ + (where), (head)->hh.tbl->num_items, _count); \ + } \ + } \ +} while (0) +#else +#define HASH_FSCK(hh,head,where) +#endif + +/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to + * the descriptor to which this macro is defined for tuning the hash function. + * The app can #include to get the prototype for write(2). */ +#ifdef HASH_EMIT_KEYS +#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \ +do { \ + unsigned _klen = fieldlen; \ + write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ + write(HASH_EMIT_KEYS, keyptr, (unsigned long)fieldlen); \ +} while (0) +#else +#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) +#endif + +/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */ +#define HASH_BER(key,keylen,hashv) \ +do { \ + unsigned _hb_keylen = (unsigned)keylen; \ + const unsigned char *_hb_key = (const unsigned char*)(key); \ + (hashv) = 0; \ + while (_hb_keylen-- != 0U) { \ + (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; \ + } \ +} while (0) + + +/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at + * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx + * (archive link: https://archive.is/Ivcan ) + */ +#define HASH_SAX(key,keylen,hashv) \ +do { \ + unsigned _sx_i; \ + const unsigned char *_hs_key = (const unsigned char*)(key); \ + hashv = 0; \ + for (_sx_i=0; _sx_i < keylen; _sx_i++) { \ + hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ + } \ +} while (0) +/* FNV-1a variation */ +#define HASH_FNV(key,keylen,hashv) \ +do { \ + unsigned _fn_i; \ + const unsigned char *_hf_key = (const unsigned char*)(key); \ + (hashv) = 2166136261U; \ + for (_fn_i=0; _fn_i < keylen; _fn_i++) { \ + hashv = hashv ^ _hf_key[_fn_i]; \ + hashv = hashv * 16777619U; \ + } \ +} while (0) + +#define HASH_OAT(key,keylen,hashv) \ +do { \ + unsigned _ho_i; \ + const unsigned char *_ho_key=(const unsigned char*)(key); \ + hashv = 0; \ + for(_ho_i=0; _ho_i < keylen; _ho_i++) { \ + hashv += _ho_key[_ho_i]; \ + hashv += (hashv << 10); \ + hashv ^= (hashv >> 6); \ + } \ + hashv += (hashv << 3); \ + hashv ^= (hashv >> 11); \ + hashv += (hashv << 15); \ +} while (0) + +#define HASH_JEN_MIX(a,b,c) \ +do { \ + a -= b; a -= c; a ^= ( c >> 13 ); \ + b -= c; b -= a; b ^= ( a << 8 ); \ + c -= a; c -= b; c ^= ( b >> 13 ); \ + a -= b; a -= c; a ^= ( c >> 12 ); \ + b -= c; b -= a; b ^= ( a << 16 ); \ + c -= a; c -= b; c ^= ( b >> 5 ); \ + a -= b; a -= c; a ^= ( c >> 3 ); \ + b -= c; b -= a; b ^= ( a << 10 ); \ + c -= a; c -= b; c ^= ( b >> 15 ); \ +} while (0) + +#define HASH_JEN(key,keylen,hashv) \ +do { \ + unsigned _hj_i,_hj_j,_hj_k; \ + unsigned const char *_hj_key=(unsigned const char*)(key); \ + hashv = 0xfeedbeefu; \ + _hj_i = _hj_j = 0x9e3779b9u; \ + _hj_k = (unsigned)(keylen); \ + while (_hj_k >= 12U) { \ + _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \ + + ( (unsigned)_hj_key[2] << 16 ) \ + + ( (unsigned)_hj_key[3] << 24 ) ); \ + _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \ + + ( (unsigned)_hj_key[6] << 16 ) \ + + ( (unsigned)_hj_key[7] << 24 ) ); \ + hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \ + + ( (unsigned)_hj_key[10] << 16 ) \ + + ( (unsigned)_hj_key[11] << 24 ) ); \ + \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ + \ + _hj_key += 12; \ + _hj_k -= 12U; \ + } \ + hashv += (unsigned)(keylen); \ + switch ( _hj_k ) { \ + case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); /* FALLTHROUGH */ \ + case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); /* FALLTHROUGH */ \ + case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); /* FALLTHROUGH */ \ + case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); /* FALLTHROUGH */ \ + case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); /* FALLTHROUGH */ \ + case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); /* FALLTHROUGH */ \ + case 5: _hj_j += _hj_key[4]; /* FALLTHROUGH */ \ + case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); /* FALLTHROUGH */ \ + case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); /* FALLTHROUGH */ \ + case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); /* FALLTHROUGH */ \ + case 1: _hj_i += _hj_key[0]; /* FALLTHROUGH */ \ + default: ; \ + } \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ +} while (0) + +/* The Paul Hsieh hash function */ +#undef get16bits +#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ + || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) +#define get16bits(d) (*((const uint16_t *) (d))) +#endif + +#if !defined (get16bits) +#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \ + +(uint32_t)(((const uint8_t *)(d))[0]) ) +#endif +#define HASH_SFH(key,keylen,hashv) \ +do { \ + unsigned const char *_sfh_key=(unsigned const char*)(key); \ + uint32_t _sfh_tmp, _sfh_len = (uint32_t)keylen; \ + \ + unsigned _sfh_rem = _sfh_len & 3U; \ + _sfh_len >>= 2; \ + hashv = 0xcafebabeu; \ + \ + /* Main loop */ \ + for (;_sfh_len > 0U; _sfh_len--) { \ + hashv += get16bits (_sfh_key); \ + _sfh_tmp = ((uint32_t)(get16bits (_sfh_key+2)) << 11) ^ hashv; \ + hashv = (hashv << 16) ^ _sfh_tmp; \ + _sfh_key += 2U*sizeof (uint16_t); \ + hashv += hashv >> 11; \ + } \ + \ + /* Handle end cases */ \ + switch (_sfh_rem) { \ + case 3: hashv += get16bits (_sfh_key); \ + hashv ^= hashv << 16; \ + hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)]) << 18; \ + hashv += hashv >> 11; \ + break; \ + case 2: hashv += get16bits (_sfh_key); \ + hashv ^= hashv << 11; \ + hashv += hashv >> 17; \ + break; \ + case 1: hashv += *_sfh_key; \ + hashv ^= hashv << 10; \ + hashv += hashv >> 1; \ + break; \ + default: ; \ + } \ + \ + /* Force "avalanching" of final 127 bits */ \ + hashv ^= hashv << 3; \ + hashv += hashv >> 5; \ + hashv ^= hashv << 4; \ + hashv += hashv >> 17; \ + hashv ^= hashv << 25; \ + hashv += hashv >> 6; \ +} while (0) + +/* iterate over items in a known bucket to find desired item */ +#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,hashval,out) \ +do { \ + if ((head).hh_head != NULL) { \ + DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (head).hh_head)); \ + } else { \ + (out) = NULL; \ + } \ + while ((out) != NULL) { \ + if ((out)->hh.hashv == (hashval) && (out)->hh.keylen == (keylen_in)) { \ + if (HASH_KEYCMP((out)->hh.key, keyptr, keylen_in) == 0) { \ + break; \ + } \ + } \ + if ((out)->hh.hh_next != NULL) { \ + DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (out)->hh.hh_next)); \ + } else { \ + (out) = NULL; \ + } \ + } \ +} while (0) + +/* add an item to a bucket */ +#define HASH_ADD_TO_BKT(head,hh,addhh,oomed) \ +do { \ + UT_hash_bucket *_ha_head = &(head); \ + _ha_head->count++; \ + (addhh)->hh_next = _ha_head->hh_head; \ + (addhh)->hh_prev = NULL; \ + if (_ha_head->hh_head != NULL) { \ + _ha_head->hh_head->hh_prev = (addhh); \ + } \ + _ha_head->hh_head = (addhh); \ + if ((_ha_head->count >= ((_ha_head->expand_mult + 1U) * HASH_BKT_CAPACITY_THRESH)) \ + && !(addhh)->tbl->noexpand) { \ + HASH_EXPAND_BUCKETS(addhh,(addhh)->tbl, oomed); \ + IF_HASH_NONFATAL_OOM( \ + if (oomed) { \ + HASH_DEL_IN_BKT(head,addhh); \ + } \ + ) \ + } \ +} while (0) + +/* remove an item from a given bucket */ +#define HASH_DEL_IN_BKT(head,delhh) \ +do { \ + UT_hash_bucket *_hd_head = &(head); \ + _hd_head->count--; \ + if (_hd_head->hh_head == (delhh)) { \ + _hd_head->hh_head = (delhh)->hh_next; \ + } \ + if ((delhh)->hh_prev) { \ + (delhh)->hh_prev->hh_next = (delhh)->hh_next; \ + } \ + if ((delhh)->hh_next) { \ + (delhh)->hh_next->hh_prev = (delhh)->hh_prev; \ + } \ +} while (0) + +/* Bucket expansion has the effect of doubling the number of buckets + * and redistributing the items into the new buckets. Ideally the + * items will distribute more or less evenly into the new buckets + * (the extent to which this is true is a measure of the quality of + * the hash function as it applies to the key domain). + * + * With the items distributed into more buckets, the chain length + * (item count) in each bucket is reduced. Thus by expanding buckets + * the hash keeps a bound on the chain length. This bounded chain + * length is the essence of how a hash provides constant time lookup. + * + * The calculation of tbl->ideal_chain_maxlen below deserves some + * explanation. First, keep in mind that we're calculating the ideal + * maximum chain length based on the *new* (doubled) bucket count. + * In fractions this is just n/b (n=number of items,b=new num buckets). + * Since the ideal chain length is an integer, we want to calculate + * ceil(n/b). We don't depend on floating point arithmetic in this + * hash, so to calculate ceil(n/b) with integers we could write + * + * ceil(n/b) = (n/b) + ((n%b)?1:0) + * + * and in fact a previous version of this hash did just that. + * But now we have improved things a bit by recognizing that b is + * always a power of two. We keep its base 2 log handy (call it lb), + * so now we can write this with a bit shift and logical AND: + * + * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0) + * + */ +#define HASH_EXPAND_BUCKETS(hh,tbl,oomed) \ +do { \ + unsigned _he_bkt; \ + unsigned _he_bkt_i; \ + struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ + UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ + _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \ + sizeof(struct UT_hash_bucket) * (tbl)->num_buckets * 2U); \ + if (!_he_new_buckets) { \ + HASH_RECORD_OOM(oomed); \ + } else { \ + uthash_bzero(_he_new_buckets, \ + sizeof(struct UT_hash_bucket) * (tbl)->num_buckets * 2U); \ + (tbl)->ideal_chain_maxlen = \ + ((tbl)->num_items >> ((tbl)->log2_num_buckets+1U)) + \ + ((((tbl)->num_items & (((tbl)->num_buckets*2U)-1U)) != 0U) ? 1U : 0U); \ + (tbl)->nonideal_items = 0; \ + for (_he_bkt_i = 0; _he_bkt_i < (tbl)->num_buckets; _he_bkt_i++) { \ + _he_thh = (tbl)->buckets[ _he_bkt_i ].hh_head; \ + while (_he_thh != NULL) { \ + _he_hh_nxt = _he_thh->hh_next; \ + HASH_TO_BKT(_he_thh->hashv, (tbl)->num_buckets * 2U, _he_bkt); \ + _he_newbkt = &(_he_new_buckets[_he_bkt]); \ + if (++(_he_newbkt->count) > (tbl)->ideal_chain_maxlen) { \ + (tbl)->nonideal_items++; \ + if (_he_newbkt->count > _he_newbkt->expand_mult * (tbl)->ideal_chain_maxlen) { \ + _he_newbkt->expand_mult++; \ + } \ + } \ + _he_thh->hh_prev = NULL; \ + _he_thh->hh_next = _he_newbkt->hh_head; \ + if (_he_newbkt->hh_head != NULL) { \ + _he_newbkt->hh_head->hh_prev = _he_thh; \ + } \ + _he_newbkt->hh_head = _he_thh; \ + _he_thh = _he_hh_nxt; \ + } \ + } \ + uthash_free((tbl)->buckets, (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \ + (tbl)->num_buckets *= 2U; \ + (tbl)->log2_num_buckets++; \ + (tbl)->buckets = _he_new_buckets; \ + (tbl)->ineff_expands = ((tbl)->nonideal_items > ((tbl)->num_items >> 1)) ? \ + ((tbl)->ineff_expands+1U) : 0U; \ + if ((tbl)->ineff_expands > 1U) { \ + (tbl)->noexpand = 1; \ + uthash_noexpand_fyi(tbl); \ + } \ + uthash_expand_fyi(tbl); \ + } \ +} while (0) + + +/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */ +/* Note that HASH_SORT assumes the hash handle name to be hh. + * HASH_SRT was added to allow the hash handle name to be passed in. */ +#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn) +#define HASH_SRT(hh,head,cmpfcn) \ +do { \ + unsigned _hs_i; \ + unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \ + struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ + if (head != NULL) { \ + _hs_insize = 1; \ + _hs_looping = 1; \ + _hs_list = &((head)->hh); \ + while (_hs_looping != 0U) { \ + _hs_p = _hs_list; \ + _hs_list = NULL; \ + _hs_tail = NULL; \ + _hs_nmerges = 0; \ + while (_hs_p != NULL) { \ + _hs_nmerges++; \ + _hs_q = _hs_p; \ + _hs_psize = 0; \ + for (_hs_i = 0; _hs_i < _hs_insize; ++_hs_i) { \ + _hs_psize++; \ + _hs_q = ((_hs_q->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ + if (_hs_q == NULL) { \ + break; \ + } \ + } \ + _hs_qsize = _hs_insize; \ + while ((_hs_psize != 0U) || ((_hs_qsize != 0U) && (_hs_q != NULL))) { \ + if (_hs_psize == 0U) { \ + _hs_e = _hs_q; \ + _hs_q = ((_hs_q->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ + _hs_qsize--; \ + } else if ((_hs_qsize == 0U) || (_hs_q == NULL)) { \ + _hs_e = _hs_p; \ + if (_hs_p != NULL) { \ + _hs_p = ((_hs_p->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL); \ + } \ + _hs_psize--; \ + } else if ((cmpfcn( \ + DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_p)), \ + DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_q)) \ + )) <= 0) { \ + _hs_e = _hs_p; \ + if (_hs_p != NULL) { \ + _hs_p = ((_hs_p->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL); \ + } \ + _hs_psize--; \ + } else { \ + _hs_e = _hs_q; \ + _hs_q = ((_hs_q->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ + _hs_qsize--; \ + } \ + if ( _hs_tail != NULL ) { \ + _hs_tail->next = ((_hs_e != NULL) ? \ + ELMT_FROM_HH((head)->hh.tbl, _hs_e) : NULL); \ + } else { \ + _hs_list = _hs_e; \ + } \ + if (_hs_e != NULL) { \ + _hs_e->prev = ((_hs_tail != NULL) ? \ + ELMT_FROM_HH((head)->hh.tbl, _hs_tail) : NULL); \ + } \ + _hs_tail = _hs_e; \ + } \ + _hs_p = _hs_q; \ + } \ + if (_hs_tail != NULL) { \ + _hs_tail->next = NULL; \ + } \ + if (_hs_nmerges <= 1U) { \ + _hs_looping = 0; \ + (head)->hh.tbl->tail = _hs_tail; \ + DECLTYPE_ASSIGN(head, ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ + } \ + _hs_insize *= 2U; \ + } \ + HASH_FSCK(hh, head, "HASH_SRT"); \ + } \ +} while (0) + +/* This function selects items from one hash into another hash. + * The end result is that the selected items have dual presence + * in both hashes. There is no copy of the items made; rather + * they are added into the new hash through a secondary hash + * hash handle that must be present in the structure. */ +#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ +do { \ + unsigned _src_bkt, _dst_bkt; \ + void *_last_elt = NULL, *_elt; \ + UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \ + ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \ + if ((src) != NULL) { \ + for (_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \ + for (_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \ + _src_hh != NULL; \ + _src_hh = _src_hh->hh_next) { \ + _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ + if (cond(_elt)) { \ + IF_HASH_NONFATAL_OOM( int _hs_oomed = 0; ) \ + _dst_hh = (UT_hash_handle*)(void*)(((char*)_elt) + _dst_hho); \ + _dst_hh->key = _src_hh->key; \ + _dst_hh->keylen = _src_hh->keylen; \ + _dst_hh->hashv = _src_hh->hashv; \ + _dst_hh->prev = _last_elt; \ + _dst_hh->next = NULL; \ + if (_last_elt_hh != NULL) { \ + _last_elt_hh->next = _elt; \ + } \ + if ((dst) == NULL) { \ + DECLTYPE_ASSIGN(dst, _elt); \ + HASH_MAKE_TABLE(hh_dst, dst, _hs_oomed); \ + IF_HASH_NONFATAL_OOM( \ + if (_hs_oomed) { \ + uthash_nonfatal_oom(_elt); \ + (dst) = NULL; \ + continue; \ + } \ + ) \ + } else { \ + _dst_hh->tbl = (dst)->hh_dst.tbl; \ + } \ + HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \ + HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt], hh_dst, _dst_hh, _hs_oomed); \ + (dst)->hh_dst.tbl->num_items++; \ + IF_HASH_NONFATAL_OOM( \ + if (_hs_oomed) { \ + HASH_ROLLBACK_BKT(hh_dst, dst, _dst_hh); \ + HASH_DELETE_HH(hh_dst, dst, _dst_hh); \ + _dst_hh->tbl = NULL; \ + uthash_nonfatal_oom(_elt); \ + continue; \ + } \ + ) \ + HASH_BLOOM_ADD(_dst_hh->tbl, _dst_hh->hashv); \ + _last_elt = _elt; \ + _last_elt_hh = _dst_hh; \ + } \ + } \ + } \ + } \ + HASH_FSCK(hh_dst, dst, "HASH_SELECT"); \ +} while (0) + +#define HASH_CLEAR(hh,head) \ +do { \ + if ((head) != NULL) { \ + HASH_BLOOM_FREE((head)->hh.tbl); \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head) = NULL; \ + } \ +} while (0) + +#define HASH_OVERHEAD(hh,head) \ + (((head) != NULL) ? ( \ + (size_t)(((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \ + ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \ + sizeof(UT_hash_table) + \ + (HASH_BLOOM_BYTELEN))) : 0U) + +#ifdef NO_DECLTYPE +#define HASH_ITER(hh,head,el,tmp) \ +for(((el)=(head)), ((*(char**)(&(tmp)))=(char*)((head!=NULL)?(head)->hh.next:NULL)); \ + (el) != NULL; ((el)=(tmp)), ((*(char**)(&(tmp)))=(char*)((tmp!=NULL)?(tmp)->hh.next:NULL))) +#else +#define HASH_ITER(hh,head,el,tmp) \ +for(((el)=(head)), ((tmp)=DECLTYPE(el)((head!=NULL)?(head)->hh.next:NULL)); \ + (el) != NULL; ((el)=(tmp)), ((tmp)=DECLTYPE(el)((tmp!=NULL)?(tmp)->hh.next:NULL))) +#endif + +/* obtain a count of items in the hash */ +#define HASH_COUNT(head) HASH_CNT(hh,head) +#define HASH_CNT(hh,head) ((head != NULL)?((head)->hh.tbl->num_items):0U) + +typedef struct UT_hash_bucket { + struct UT_hash_handle *hh_head; + unsigned count; + + /* expand_mult is normally set to 0. In this situation, the max chain length + * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If + * the bucket's chain exceeds this length, bucket expansion is triggered). + * However, setting expand_mult to a non-zero value delays bucket expansion + * (that would be triggered by additions to this particular bucket) + * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH. + * (The multiplier is simply expand_mult+1). The whole idea of this + * multiplier is to reduce bucket expansions, since they are expensive, in + * situations where we know that a particular bucket tends to be overused. + * It is better to let its chain length grow to a longer yet-still-bounded + * value, than to do an O(n) bucket expansion too often. + */ + unsigned expand_mult; + +} UT_hash_bucket; + +/* random signature used only to find hash tables in external analysis */ +#define HASH_SIGNATURE 0xa0111fe1u +#define HASH_BLOOM_SIGNATURE 0xb12220f2u + +typedef struct UT_hash_table { + UT_hash_bucket *buckets; + unsigned num_buckets, log2_num_buckets; + unsigned num_items; + struct UT_hash_handle *tail; /* tail hh in app order, for fast append */ + ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */ + + /* in an ideal situation (all buckets used equally), no bucket would have + * more than ceil(#items/#buckets) items. that's the ideal chain length. */ + unsigned ideal_chain_maxlen; + + /* nonideal_items is the number of items in the hash whose chain position + * exceeds the ideal chain maxlen. these items pay the penalty for an uneven + * hash distribution; reaching them in a chain traversal takes >ideal steps */ + unsigned nonideal_items; + + /* ineffective expands occur when a bucket doubling was performed, but + * afterward, more than half the items in the hash had nonideal chain + * positions. If this happens on two consecutive expansions we inhibit any + * further expansion, as it's not helping; this happens when the hash + * function isn't a good fit for the key domain. When expansion is inhibited + * the hash will still work, albeit no longer in constant time. */ + unsigned ineff_expands, noexpand; + + uint32_t signature; /* used only to find hash tables in external analysis */ +#ifdef HASH_BLOOM + uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ + uint8_t *bloom_bv; + uint8_t bloom_nbits; +#endif + +} UT_hash_table; + +typedef struct UT_hash_handle { + struct UT_hash_table *tbl; + void *prev; /* prev element in app order */ + void *next; /* next element in app order */ + struct UT_hash_handle *hh_prev; /* previous hh in bucket order */ + struct UT_hash_handle *hh_next; /* next hh in bucket order */ + const void *key; /* ptr to enclosing struct's key */ + unsigned keylen; /* enclosing struct's key len */ + unsigned hashv; /* result of hash-fcn(key) */ +} UT_hash_handle; + +#endif /* UTHASH_H */ diff --git a/src/ocre/include/uthash/utlist.h b/src/ocre/include/uthash/utlist.h new file mode 100644 index 00000000..275e4223 --- /dev/null +++ b/src/ocre/include/uthash/utlist.h @@ -0,0 +1,1076 @@ +/* +Copyright (c) 2007-2025, Troy D. Hanson https://troydhanson.github.io/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef UTLIST_H +#define UTLIST_H + +#define UTLIST_VERSION 2.3.0 + +#include + +/* + * This file contains macros to manipulate singly and doubly-linked lists. + * + * 1. LL_ macros: singly-linked lists. + * 2. DL_ macros: doubly-linked lists. + * 3. CDL_ macros: circular doubly-linked lists. + * + * To use singly-linked lists, your structure must have a "next" pointer. + * To use doubly-linked lists, your structure must "prev" and "next" pointers. + * Either way, the pointer to the head of the list must be initialized to NULL. + * + * ----------------.EXAMPLE ------------------------- + * struct item { + * int id; + * struct item *prev, *next; + * } + * + * struct item *list = NULL: + * + * int main() { + * struct item *item; + * ... allocate and populate item ... + * DL_APPEND(list, item); + * } + * -------------------------------------------------- + * + * For doubly-linked lists, the append and delete macros are O(1) + * For singly-linked lists, append and delete are O(n) but prepend is O(1) + * The sort macro is O(n log(n)) for all types of single/double/circular lists. + */ + +/* These macros use decltype or the earlier __typeof GNU extension. + As decltype is only available in newer compilers (VS2010 or gcc 4.3+ + when compiling c++ source) this code uses whatever method is needed + or, for VS2008 where neither is available, uses casting workarounds. */ +#if !defined(LDECLTYPE) && !defined(NO_DECLTYPE) +#if defined(_MSC_VER) /* MS compiler */ +#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ +#define LDECLTYPE(x) decltype(x) +#else /* VS2008 or older (or VS2010 in C mode) */ +#define NO_DECLTYPE +#endif +#elif defined(__MCST__) /* Elbrus C Compiler */ +#define LDECLTYPE(x) __typeof(x) +#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__) +#define NO_DECLTYPE +#else /* GNU, Sun and other compilers */ +#define LDECLTYPE(x) __typeof(x) +#endif +#endif + +/* for VS2008 we use some workarounds to get around the lack of decltype, + * namely, we always reassign our tmp variable to the list head if we need + * to dereference its prev/next pointers, and save/restore the real head.*/ +#ifdef NO_DECLTYPE +#define IF_NO_DECLTYPE(x) x +#define LDECLTYPE(x) char* +#define UTLIST_SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); } +#define UTLIST_NEXT(elt,list,next) ((char*)((list)->next)) +#define UTLIST_NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); } +/* #define UTLIST_PREV(elt,list,prev) ((char*)((list)->prev)) */ +#define UTLIST_PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); } +#define UTLIST_RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; } +#define UTLIST_CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); } +#else +#define IF_NO_DECLTYPE(x) +#define UTLIST_SV(elt,list) +#define UTLIST_NEXT(elt,list,next) ((elt)->next) +#define UTLIST_NEXTASGN(elt,list,to,next) ((elt)->next)=(to) +/* #define UTLIST_PREV(elt,list,prev) ((elt)->prev) */ +#define UTLIST_PREVASGN(elt,list,to,prev) ((elt)->prev)=(to) +#define UTLIST_RS(list) +#define UTLIST_CASTASGN(a,b) (a)=(b) +#endif + +/****************************************************************************** + * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort * + * Unwieldy variable names used here to avoid shadowing passed-in variables. * + *****************************************************************************/ +#define LL_SORT(list, cmp) \ + LL_SORT2(list, cmp, next) + +#define LL_SORT2(list, cmp, next) \ +do { \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;) \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + UTLIST_CASTASGN(_ls_p,list); \ + (list) = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); \ + if (!_ls_q) break; \ + } \ + _ls_qsize = _ls_insize; \ + while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + } else if (_ls_qsize == 0 || !_ls_q) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + } else if (cmp(_ls_p,_ls_q) <= 0) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + } else { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + } \ + if (_ls_tail) { \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ + } else { \ + UTLIST_CASTASGN(list,_ls_e); \ + } \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + if (_ls_tail) { \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list); \ + } \ + if (_ls_nmerges <= 1) { \ + _ls_looping=0; \ + } \ + _ls_insize *= 2; \ + } \ + } \ +} while (0) + + +#define DL_SORT(list, cmp) \ + DL_SORT2(list, cmp, prev, next) + +#define DL_SORT2(list, cmp, prev, next) \ +do { \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;) \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + UTLIST_CASTASGN(_ls_p,list); \ + (list) = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); \ + if (!_ls_q) break; \ + } \ + _ls_qsize = _ls_insize; \ + while ((_ls_psize > 0) || ((_ls_qsize > 0) && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + } else if ((_ls_qsize == 0) || (!_ls_q)) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + } else if (cmp(_ls_p,_ls_q) <= 0) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + } else { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + } \ + if (_ls_tail) { \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ + } else { \ + UTLIST_CASTASGN(list,_ls_e); \ + } \ + UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list); \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + UTLIST_CASTASGN((list)->prev, _ls_tail); \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list); \ + if (_ls_nmerges <= 1) { \ + _ls_looping=0; \ + } \ + _ls_insize *= 2; \ + } \ + } \ +} while (0) + +#define CDL_SORT(list, cmp) \ + CDL_SORT2(list, cmp, prev, next) + +#define CDL_SORT2(list, cmp, prev, next) \ +do { \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + LDECLTYPE(list) _ls_oldhead; \ + LDECLTYPE(list) _tmp; \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + UTLIST_CASTASGN(_ls_p,list); \ + UTLIST_CASTASGN(_ls_oldhead,list); \ + (list) = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + UTLIST_SV(_ls_q,list); \ + if (UTLIST_NEXT(_ls_q,list,next) == _ls_oldhead) { \ + _ls_q = NULL; \ + } else { \ + _ls_q = UTLIST_NEXT(_ls_q,list,next); \ + } \ + UTLIST_RS(list); \ + if (!_ls_q) break; \ + } \ + _ls_qsize = _ls_insize; \ + while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ + } else if (_ls_qsize == 0 || !_ls_q) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ + } else if (cmp(_ls_p,_ls_q) <= 0) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ + } else { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ + } \ + if (_ls_tail) { \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ + } else { \ + UTLIST_CASTASGN(list,_ls_e); \ + } \ + UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list); \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + UTLIST_CASTASGN((list)->prev,_ls_tail); \ + UTLIST_CASTASGN(_tmp,list); \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_tmp,next); UTLIST_RS(list); \ + if (_ls_nmerges <= 1) { \ + _ls_looping=0; \ + } \ + _ls_insize *= 2; \ + } \ + } \ +} while (0) + +/****************************************************************************** + * singly linked list macros (non-circular) * + *****************************************************************************/ +#define LL_PREPEND(head,add) \ + LL_PREPEND2(head,add,next) + +#define LL_PREPEND2(head,add,next) \ +do { \ + (add)->next = (head); \ + (head) = (add); \ +} while (0) + +#define LL_CONCAT(head1,head2) \ + LL_CONCAT2(head1,head2,next) + +#define LL_CONCAT2(head1,head2,next) \ +do { \ + LDECLTYPE(head1) _tmp; \ + if (head1) { \ + _tmp = (head1); \ + while (_tmp->next) { _tmp = _tmp->next; } \ + _tmp->next=(head2); \ + } else { \ + (head1)=(head2); \ + } \ +} while (0) + +#define LL_APPEND(head,add) \ + LL_APPEND2(head,add,next) + +#define LL_APPEND2(head,add,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + (add)->next=NULL; \ + if (head) { \ + _tmp = (head); \ + while (_tmp->next) { _tmp = _tmp->next; } \ + _tmp->next=(add); \ + } else { \ + (head)=(add); \ + } \ +} while (0) + +#define LL_INSERT_INORDER(head,add,cmp) \ + LL_INSERT_INORDER2(head,add,cmp,next) + +#define LL_INSERT_INORDER2(head,add,cmp,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + if (head) { \ + LL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ + LL_APPEND_ELEM2(head, _tmp, add, next); \ + } else { \ + (head) = (add); \ + (head)->next = NULL; \ + } \ +} while (0) + +#define LL_LOWER_BOUND(head,elt,like,cmp) \ + LL_LOWER_BOUND2(head,elt,like,cmp,next) + +#define LL_LOWER_BOUND2(head,elt,like,cmp,next) \ + do { \ + if ((head) == NULL || (cmp(head, like)) >= 0) { \ + (elt) = NULL; \ + } else { \ + for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \ + if (cmp((elt)->next, like) >= 0) { \ + break; \ + } \ + } \ + } \ + } while (0) + +#define LL_DELETE(head,del) \ + LL_DELETE2(head,del,next) + +#define LL_DELETE2(head,del,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + if ((head) == (del)) { \ + (head)=(head)->next; \ + } else { \ + _tmp = (head); \ + while (_tmp->next && (_tmp->next != (del))) { \ + _tmp = _tmp->next; \ + } \ + if (_tmp->next) { \ + _tmp->next = (del)->next; \ + } \ + } \ +} while (0) + +#define LL_COUNT(head,el,counter) \ + LL_COUNT2(head,el,counter,next) \ + +#define LL_COUNT2(head,el,counter,next) \ +do { \ + (counter) = 0; \ + LL_FOREACH2(head,el,next) { ++(counter); } \ +} while (0) + +#define LL_FOREACH(head,el) \ + LL_FOREACH2(head,el,next) + +#define LL_FOREACH2(head,el,next) \ + for ((el) = (head); el; (el) = (el)->next) + +#define LL_FOREACH_SAFE(head,el,tmp) \ + LL_FOREACH_SAFE2(head,el,tmp,next) + +#define LL_FOREACH_SAFE2(head,el,tmp,next) \ + for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp)) + +#define LL_SEARCH_SCALAR(head,out,field,val) \ + LL_SEARCH_SCALAR2(head,out,field,val,next) + +#define LL_SEARCH_SCALAR2(head,out,field,val,next) \ +do { \ + LL_FOREACH2(head,out,next) { \ + if ((out)->field == (val)) break; \ + } \ +} while (0) + +#define LL_SEARCH(head,out,elt,cmp) \ + LL_SEARCH2(head,out,elt,cmp,next) + +#define LL_SEARCH2(head,out,elt,cmp,next) \ +do { \ + LL_FOREACH2(head,out,next) { \ + if ((cmp(out,elt))==0) break; \ + } \ +} while (0) + +#define LL_REPLACE_ELEM2(head, el, add, next) \ +do { \ + LDECLTYPE(head) _tmp; \ + assert((head) != NULL); \ + assert((el) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el)->next; \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + _tmp = (head); \ + while (_tmp->next && (_tmp->next != (el))) { \ + _tmp = _tmp->next; \ + } \ + if (_tmp->next) { \ + _tmp->next = (add); \ + } \ + } \ +} while (0) + +#define LL_REPLACE_ELEM(head, el, add) \ + LL_REPLACE_ELEM2(head, el, add, next) + +#define LL_PREPEND_ELEM2(head, el, add, next) \ +do { \ + if (el) { \ + LDECLTYPE(head) _tmp; \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + _tmp = (head); \ + while (_tmp->next && (_tmp->next != (el))) { \ + _tmp = _tmp->next; \ + } \ + if (_tmp->next) { \ + _tmp->next = (add); \ + } \ + } \ + } else { \ + LL_APPEND2(head, add, next); \ + } \ +} while (0) \ + +#define LL_PREPEND_ELEM(head, el, add) \ + LL_PREPEND_ELEM2(head, el, add, next) + +#define LL_APPEND_ELEM2(head, el, add, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el)->next; \ + (el)->next = (add); \ + } else { \ + LL_PREPEND2(head, add, next); \ + } \ +} while (0) \ + +#define LL_APPEND_ELEM(head, el, add) \ + LL_APPEND_ELEM2(head, el, add, next) + +#ifdef NO_DECLTYPE +/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ + +#undef LL_CONCAT2 +#define LL_CONCAT2(head1,head2,next) \ +do { \ + char *_tmp; \ + if (head1) { \ + _tmp = (char*)(head1); \ + while ((head1)->next) { (head1) = (head1)->next; } \ + (head1)->next = (head2); \ + UTLIST_RS(head1); \ + } else { \ + (head1)=(head2); \ + } \ +} while (0) + +#undef LL_APPEND2 +#define LL_APPEND2(head,add,next) \ +do { \ + if (head) { \ + (add)->next = head; /* use add->next as a temp variable */ \ + while ((add)->next->next) { (add)->next = (add)->next->next; } \ + (add)->next->next=(add); \ + } else { \ + (head)=(add); \ + } \ + (add)->next=NULL; \ +} while (0) + +#undef LL_INSERT_INORDER2 +#define LL_INSERT_INORDER2(head,add,cmp,next) \ +do { \ + if ((head) == NULL || (cmp(head, add)) >= 0) { \ + (add)->next = (head); \ + (head) = (add); \ + } else { \ + char *_tmp = (char*)(head); \ + while ((head)->next != NULL && (cmp((head)->next, add)) < 0) { \ + (head) = (head)->next; \ + } \ + (add)->next = (head)->next; \ + (head)->next = (add); \ + UTLIST_RS(head); \ + } \ +} while (0) + +#undef LL_DELETE2 +#define LL_DELETE2(head,del,next) \ +do { \ + if ((head) == (del)) { \ + (head)=(head)->next; \ + } else { \ + char *_tmp = (char*)(head); \ + while ((head)->next && ((head)->next != (del))) { \ + (head) = (head)->next; \ + } \ + if ((head)->next) { \ + (head)->next = ((del)->next); \ + } \ + UTLIST_RS(head); \ + } \ +} while (0) + +#undef LL_REPLACE_ELEM2 +#define LL_REPLACE_ELEM2(head, el, add, next) \ +do { \ + assert((head) != NULL); \ + assert((el) != NULL); \ + assert((add) != NULL); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + (add)->next = head; \ + while ((add)->next->next && ((add)->next->next != (el))) { \ + (add)->next = (add)->next->next; \ + } \ + if ((add)->next->next) { \ + (add)->next->next = (add); \ + } \ + } \ + (add)->next = (el)->next; \ +} while (0) + +#undef LL_PREPEND_ELEM2 +#define LL_PREPEND_ELEM2(head, el, add, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + (add)->next = (head); \ + while ((add)->next->next && ((add)->next->next != (el))) { \ + (add)->next = (add)->next->next; \ + } \ + if ((add)->next->next) { \ + (add)->next->next = (add); \ + } \ + } \ + (add)->next = (el); \ + } else { \ + LL_APPEND2(head, add, next); \ + } \ +} while (0) \ + +#endif /* NO_DECLTYPE */ + +/****************************************************************************** + * doubly linked list macros (non-circular) * + *****************************************************************************/ +#define DL_PREPEND(head,add) \ + DL_PREPEND2(head,add,prev,next) + +#define DL_PREPEND2(head,add,prev,next) \ +do { \ + (add)->next = (head); \ + if (head) { \ + (add)->prev = (head)->prev; \ + (head)->prev = (add); \ + } else { \ + (add)->prev = (add); \ + } \ + (head) = (add); \ +} while (0) + +#define DL_APPEND(head,add) \ + DL_APPEND2(head,add,prev,next) + +#define DL_APPEND2(head,add,prev,next) \ +do { \ + if (head) { \ + (add)->prev = (head)->prev; \ + (head)->prev->next = (add); \ + (head)->prev = (add); \ + (add)->next = NULL; \ + } else { \ + (head)=(add); \ + (head)->prev = (head); \ + (head)->next = NULL; \ + } \ +} while (0) + +#define DL_INSERT_INORDER(head,add,cmp) \ + DL_INSERT_INORDER2(head,add,cmp,prev,next) + +#define DL_INSERT_INORDER2(head,add,cmp,prev,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + if (head) { \ + DL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ + DL_APPEND_ELEM2(head, _tmp, add, prev, next); \ + } else { \ + (head) = (add); \ + (head)->prev = (head); \ + (head)->next = NULL; \ + } \ +} while (0) + +#define DL_LOWER_BOUND(head,elt,like,cmp) \ + DL_LOWER_BOUND2(head,elt,like,cmp,next) + +#define DL_LOWER_BOUND2(head,elt,like,cmp,next) \ +do { \ + if ((head) == NULL || (cmp(head, like)) >= 0) { \ + (elt) = NULL; \ + } else { \ + for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \ + if ((cmp((elt)->next, like)) >= 0) { \ + break; \ + } \ + } \ + } \ +} while (0) + +#define DL_CONCAT(head1,head2) \ + DL_CONCAT2(head1,head2,prev,next) + +#define DL_CONCAT2(head1,head2,prev,next) \ +do { \ + LDECLTYPE(head1) _tmp; \ + if (head2) { \ + if (head1) { \ + UTLIST_CASTASGN(_tmp, (head2)->prev); \ + (head2)->prev = (head1)->prev; \ + (head1)->prev->next = (head2); \ + UTLIST_CASTASGN((head1)->prev, _tmp); \ + } else { \ + (head1)=(head2); \ + } \ + } \ +} while (0) + +#define DL_DELETE(head,del) \ + DL_DELETE2(head,del,prev,next) + +#define DL_DELETE2(head,del,prev,next) \ +do { \ + assert((head) != NULL); \ + assert((del)->prev != NULL); \ + if ((del)->prev == (del)) { \ + (head)=NULL; \ + } else if ((del) == (head)) { \ + assert((del)->next != NULL); \ + (del)->next->prev = (del)->prev; \ + (head) = (del)->next; \ + } else { \ + (del)->prev->next = (del)->next; \ + if ((del)->next) { \ + (del)->next->prev = (del)->prev; \ + } else { \ + (head)->prev = (del)->prev; \ + } \ + } \ +} while (0) + +#define DL_COUNT(head,el,counter) \ + DL_COUNT2(head,el,counter,next) \ + +#define DL_COUNT2(head,el,counter,next) \ +do { \ + (counter) = 0; \ + DL_FOREACH2(head,el,next) { ++(counter); } \ +} while (0) + +#define DL_FOREACH(head,el) \ + DL_FOREACH2(head,el,next) + +#define DL_FOREACH2(head,el,next) \ + for ((el) = (head); el; (el) = (el)->next) + +/* this version is safe for deleting the elements during iteration */ +#define DL_FOREACH_SAFE(head,el,tmp) \ + DL_FOREACH_SAFE2(head,el,tmp,next) + +#define DL_FOREACH_SAFE2(head,el,tmp,next) \ + for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp)) + +/* these are identical to their singly-linked list counterparts */ +#define DL_SEARCH_SCALAR LL_SEARCH_SCALAR +#define DL_SEARCH LL_SEARCH +#define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2 +#define DL_SEARCH2 LL_SEARCH2 + +#define DL_REPLACE_ELEM2(head, el, add, prev, next) \ +do { \ + assert((head) != NULL); \ + assert((el) != NULL); \ + assert((add) != NULL); \ + if ((head) == (el)) { \ + (head) = (add); \ + (add)->next = (el)->next; \ + if ((el)->next == NULL) { \ + (add)->prev = (add); \ + } else { \ + (add)->prev = (el)->prev; \ + (add)->next->prev = (add); \ + } \ + } else { \ + (add)->next = (el)->next; \ + (add)->prev = (el)->prev; \ + (add)->prev->next = (add); \ + if ((el)->next == NULL) { \ + (head)->prev = (add); \ + } else { \ + (add)->next->prev = (add); \ + } \ + } \ +} while (0) + +#define DL_REPLACE_ELEM(head, el, add) \ + DL_REPLACE_ELEM2(head, el, add, prev, next) + +#define DL_PREPEND_ELEM2(head, el, add, prev, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el); \ + (add)->prev = (el)->prev; \ + (el)->prev = (add); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + (add)->prev->next = (add); \ + } \ + } else { \ + DL_APPEND2(head, add, prev, next); \ + } \ +} while (0) \ + +#define DL_PREPEND_ELEM(head, el, add) \ + DL_PREPEND_ELEM2(head, el, add, prev, next) + +#define DL_APPEND_ELEM2(head, el, add, prev, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el)->next; \ + (add)->prev = (el); \ + (el)->next = (add); \ + if ((add)->next) { \ + (add)->next->prev = (add); \ + } else { \ + (head)->prev = (add); \ + } \ + } else { \ + DL_PREPEND2(head, add, prev, next); \ + } \ +} while (0) \ + +#define DL_APPEND_ELEM(head, el, add) \ + DL_APPEND_ELEM2(head, el, add, prev, next) + +#ifdef NO_DECLTYPE +/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ + +#undef DL_INSERT_INORDER2 +#define DL_INSERT_INORDER2(head,add,cmp,prev,next) \ +do { \ + if ((head) == NULL) { \ + (add)->prev = (add); \ + (add)->next = NULL; \ + (head) = (add); \ + } else if ((cmp(head, add)) >= 0) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (head)->prev = (add); \ + (head) = (add); \ + } else { \ + char *_tmp = (char*)(head); \ + while ((head)->next && (cmp((head)->next, add)) < 0) { \ + (head) = (head)->next; \ + } \ + (add)->prev = (head); \ + (add)->next = (head)->next; \ + (head)->next = (add); \ + UTLIST_RS(head); \ + if ((add)->next) { \ + (add)->next->prev = (add); \ + } else { \ + (head)->prev = (add); \ + } \ + } \ +} while (0) +#endif /* NO_DECLTYPE */ + +/****************************************************************************** + * circular doubly linked list macros * + *****************************************************************************/ +#define CDL_APPEND(head,add) \ + CDL_APPEND2(head,add,prev,next) + +#define CDL_APPEND2(head,add,prev,next) \ +do { \ + if (head) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (head)->prev = (add); \ + (add)->prev->next = (add); \ + } else { \ + (add)->prev = (add); \ + (add)->next = (add); \ + (head) = (add); \ + } \ +} while (0) + +#define CDL_PREPEND(head,add) \ + CDL_PREPEND2(head,add,prev,next) + +#define CDL_PREPEND2(head,add,prev,next) \ +do { \ + if (head) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (head)->prev = (add); \ + (add)->prev->next = (add); \ + } else { \ + (add)->prev = (add); \ + (add)->next = (add); \ + } \ + (head) = (add); \ +} while (0) + +#define CDL_INSERT_INORDER(head,add,cmp) \ + CDL_INSERT_INORDER2(head,add,cmp,prev,next) + +#define CDL_INSERT_INORDER2(head,add,cmp,prev,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + if (head) { \ + CDL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ + CDL_APPEND_ELEM2(head, _tmp, add, prev, next); \ + } else { \ + (head) = (add); \ + (head)->next = (head); \ + (head)->prev = (head); \ + } \ +} while (0) + +#define CDL_LOWER_BOUND(head,elt,like,cmp) \ + CDL_LOWER_BOUND2(head,elt,like,cmp,next) + +#define CDL_LOWER_BOUND2(head,elt,like,cmp,next) \ +do { \ + if ((head) == NULL || (cmp(head, like)) >= 0) { \ + (elt) = NULL; \ + } else { \ + for ((elt) = (head); (elt)->next != (head); (elt) = (elt)->next) { \ + if ((cmp((elt)->next, like)) >= 0) { \ + break; \ + } \ + } \ + } \ +} while (0) + +#define CDL_DELETE(head,del) \ + CDL_DELETE2(head,del,prev,next) + +#define CDL_DELETE2(head,del,prev,next) \ +do { \ + if (((head)==(del)) && ((head)->next == (head))) { \ + (head) = NULL; \ + } else { \ + (del)->next->prev = (del)->prev; \ + (del)->prev->next = (del)->next; \ + if ((del) == (head)) (head)=(del)->next; \ + } \ +} while (0) + +#define CDL_COUNT(head,el,counter) \ + CDL_COUNT2(head,el,counter,next) \ + +#define CDL_COUNT2(head, el, counter,next) \ +do { \ + (counter) = 0; \ + CDL_FOREACH2(head,el,next) { ++(counter); } \ +} while (0) + +#define CDL_FOREACH(head,el) \ + CDL_FOREACH2(head,el,next) + +#define CDL_FOREACH2(head,el,next) \ + for ((el)=(head);el;(el)=(((el)->next==(head)) ? NULL : (el)->next)) + +#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \ + CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) + +#define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) \ + for ((el) = (head), (tmp1) = (head) ? (head)->prev : NULL; \ + (el) && ((tmp2) = (el)->next, 1); \ + (el) = ((el) == (tmp1) ? NULL : (tmp2))) + +#define CDL_SEARCH_SCALAR(head,out,field,val) \ + CDL_SEARCH_SCALAR2(head,out,field,val,next) + +#define CDL_SEARCH_SCALAR2(head,out,field,val,next) \ +do { \ + CDL_FOREACH2(head,out,next) { \ + if ((out)->field == (val)) break; \ + } \ +} while (0) + +#define CDL_SEARCH(head,out,elt,cmp) \ + CDL_SEARCH2(head,out,elt,cmp,next) + +#define CDL_SEARCH2(head,out,elt,cmp,next) \ +do { \ + CDL_FOREACH2(head,out,next) { \ + if ((cmp(out,elt))==0) break; \ + } \ +} while (0) + +#define CDL_REPLACE_ELEM2(head, el, add, prev, next) \ +do { \ + assert((head) != NULL); \ + assert((el) != NULL); \ + assert((add) != NULL); \ + if ((el)->next == (el)) { \ + (add)->next = (add); \ + (add)->prev = (add); \ + (head) = (add); \ + } else { \ + (add)->next = (el)->next; \ + (add)->prev = (el)->prev; \ + (add)->next->prev = (add); \ + (add)->prev->next = (add); \ + if ((head) == (el)) { \ + (head) = (add); \ + } \ + } \ +} while (0) + +#define CDL_REPLACE_ELEM(head, el, add) \ + CDL_REPLACE_ELEM2(head, el, add, prev, next) + +#define CDL_PREPEND_ELEM2(head, el, add, prev, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el); \ + (add)->prev = (el)->prev; \ + (el)->prev = (add); \ + (add)->prev->next = (add); \ + if ((head) == (el)) { \ + (head) = (add); \ + } \ + } else { \ + CDL_APPEND2(head, add, prev, next); \ + } \ +} while (0) + +#define CDL_PREPEND_ELEM(head, el, add) \ + CDL_PREPEND_ELEM2(head, el, add, prev, next) + +#define CDL_APPEND_ELEM2(head, el, add, prev, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el)->next; \ + (add)->prev = (el); \ + (el)->next = (add); \ + (add)->next->prev = (add); \ + } else { \ + CDL_PREPEND2(head, add, prev, next); \ + } \ +} while (0) + +#define CDL_APPEND_ELEM(head, el, add) \ + CDL_APPEND_ELEM2(head, el, add, prev, next) + +#ifdef NO_DECLTYPE +/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ + +#undef CDL_INSERT_INORDER2 +#define CDL_INSERT_INORDER2(head,add,cmp,prev,next) \ +do { \ + if ((head) == NULL) { \ + (add)->prev = (add); \ + (add)->next = (add); \ + (head) = (add); \ + } else if ((cmp(head, add)) >= 0) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (add)->prev->next = (add); \ + (head)->prev = (add); \ + (head) = (add); \ + } else { \ + char *_tmp = (char*)(head); \ + while ((char*)(head)->next != _tmp && (cmp((head)->next, add)) < 0) { \ + (head) = (head)->next; \ + } \ + (add)->prev = (head); \ + (add)->next = (head)->next; \ + (add)->next->prev = (add); \ + (head)->next = (add); \ + UTLIST_RS(head); \ + } \ +} while (0) +#endif /* NO_DECLTYPE */ + +#endif /* UTLIST_H */ diff --git a/src/ocre/include/uthash/utringbuffer.h b/src/ocre/include/uthash/utringbuffer.h new file mode 100644 index 00000000..3309aeba --- /dev/null +++ b/src/ocre/include/uthash/utringbuffer.h @@ -0,0 +1,108 @@ +/* +Copyright (c) 2015-2025, Troy D. Hanson https://troydhanson.github.io/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* a ring-buffer implementation using macros + */ +#ifndef UTRINGBUFFER_H +#define UTRINGBUFFER_H + +#define UTRINGBUFFER_VERSION 2.3.0 + +#include +#include +#include "utarray.h" // for "UT_icd" + +typedef struct { + unsigned i; /* index of next available slot; wraps at n */ + unsigned n; /* capacity */ + unsigned char f; /* full */ + UT_icd icd; /* initializer, copy and destructor functions */ + char *d; /* n slots of size icd->sz */ +} UT_ringbuffer; + +#define utringbuffer_init(a, _n, _icd) do { \ + memset(a, 0, sizeof(UT_ringbuffer)); \ + (a)->icd = *(_icd); \ + (a)->n = (_n); \ + if ((a)->n) { (a)->d = (char*)malloc((a)->n * (_icd)->sz); } \ +} while(0) + +#define utringbuffer_clear(a) do { \ + if ((a)->icd.dtor) { \ + if ((a)->f) { \ + unsigned _ut_i; \ + for (_ut_i = 0; _ut_i < (a)->n; ++_ut_i) { \ + (a)->icd.dtor(utringbuffer_eltptr(a, _ut_i)); \ + } \ + } else { \ + unsigned _ut_i; \ + for (_ut_i = 0; _ut_i < (a)->i; ++_ut_i) { \ + (a)->icd.dtor(utringbuffer_eltptr(a, _ut_i)); \ + } \ + } \ + } \ + (a)->i = 0; \ + (a)->f = 0; \ +} while(0) + +#define utringbuffer_done(a) do { \ + utringbuffer_clear(a); \ + free((a)->d); (a)->d = NULL; \ + (a)->n = 0; \ +} while(0) + +#define utringbuffer_new(a,n,_icd) do { \ + a = (UT_ringbuffer*)malloc(sizeof(UT_ringbuffer)); \ + utringbuffer_init(a, n, _icd); \ +} while(0) + +#define utringbuffer_free(a) do { \ + utringbuffer_done(a); \ + free(a); \ +} while(0) + +#define utringbuffer_push_back(a,p) do { \ + if ((a)->icd.dtor && (a)->f) { (a)->icd.dtor(_utringbuffer_internalptr(a,(a)->i)); } \ + if ((a)->icd.copy) { (a)->icd.copy( _utringbuffer_internalptr(a,(a)->i), p); } \ + else { memcpy(_utringbuffer_internalptr(a,(a)->i), p, (a)->icd.sz); }; \ + if (++(a)->i == (a)->n) { (a)->i = 0; (a)->f = 1; } \ +} while(0) + +#define utringbuffer_len(a) ((a)->f ? (a)->n : (a)->i) +#define utringbuffer_empty(a) ((a)->i == 0 && !(a)->f) +#define utringbuffer_full(a) ((a)->f != 0) + +#define _utringbuffer_real_idx(a,j) ((a)->f ? ((j) + (a)->i) % (a)->n : (j)) +#define _utringbuffer_internalptr(a,j) ((void*)((a)->d + ((a)->icd.sz * (j)))) +#define utringbuffer_eltptr(a,j) ((0 <= (j) && (j) < utringbuffer_len(a)) ? _utringbuffer_internalptr(a,_utringbuffer_real_idx(a,j)) : NULL) + +#define _utringbuffer_fake_idx(a,j) ((a)->f ? ((j) + (a)->n - (a)->i) % (a)->n : (j)) +#define _utringbuffer_internalidx(a,e) (((char*)(e) >= (a)->d) ? (((char*)(e) - (a)->d)/(a)->icd.sz) : -1) +#define utringbuffer_eltidx(a,e) _utringbuffer_fake_idx(a, _utringbuffer_internalidx(a,e)) + +#define utringbuffer_front(a) utringbuffer_eltptr(a,0) +#define utringbuffer_next(a,e) ((e)==NULL ? utringbuffer_front(a) : utringbuffer_eltptr(a, utringbuffer_eltidx(a,e)+1)) +#define utringbuffer_prev(a,e) ((e)==NULL ? utringbuffer_back(a) : utringbuffer_eltptr(a, utringbuffer_eltidx(a,e)-1)) +#define utringbuffer_back(a) (utringbuffer_empty(a) ? NULL : utringbuffer_eltptr(a, utringbuffer_len(a) - 1)) + +#endif /* UTRINGBUFFER_H */ diff --git a/src/ocre/include/uthash/utstack.h b/src/ocre/include/uthash/utstack.h new file mode 100644 index 00000000..d71bcdb1 --- /dev/null +++ b/src/ocre/include/uthash/utstack.h @@ -0,0 +1,88 @@ +/* +Copyright (c) 2018-2025, Troy D. Hanson https://troydhanson.github.io/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef UTSTACK_H +#define UTSTACK_H + +#define UTSTACK_VERSION 2.3.0 + +/* + * This file contains macros to manipulate a singly-linked list as a stack. + * + * To use utstack, your structure must have a "next" pointer. + * + * ----------------.EXAMPLE ------------------------- + * struct item { + * int id; + * struct item *next; + * }; + * + * struct item *stack = NULL; + * + * int main() { + * int count; + * struct item *tmp; + * struct item *item = malloc(sizeof *item); + * item->id = 42; + * STACK_COUNT(stack, tmp, count); assert(count == 0); + * STACK_PUSH(stack, item); + * STACK_COUNT(stack, tmp, count); assert(count == 1); + * STACK_POP(stack, item); + * free(item); + * STACK_COUNT(stack, tmp, count); assert(count == 0); + * } + * -------------------------------------------------- + */ + +#define STACK_TOP(head) (head) + +#define STACK_EMPTY(head) (!(head)) + +#define STACK_PUSH(head,add) \ + STACK_PUSH2(head,add,next) + +#define STACK_PUSH2(head,add,next) \ +do { \ + (add)->next = (head); \ + (head) = (add); \ +} while (0) + +#define STACK_POP(head,result) \ + STACK_POP2(head,result,next) + +#define STACK_POP2(head,result,next) \ +do { \ + (result) = (head); \ + (head) = (head)->next; \ +} while (0) + +#define STACK_COUNT(head,el,counter) \ + STACK_COUNT2(head,el,counter,next) \ + +#define STACK_COUNT2(head,el,counter,next) \ +do { \ + (counter) = 0; \ + for ((el) = (head); el; (el) = (el)->next) { ++(counter); } \ +} while (0) + +#endif /* UTSTACK_H */ diff --git a/src/ocre/include/uthash/utstring.h b/src/ocre/include/uthash/utstring.h new file mode 100644 index 00000000..264d5b4f --- /dev/null +++ b/src/ocre/include/uthash/utstring.h @@ -0,0 +1,407 @@ +/* +Copyright (c) 2008-2025, Troy D. Hanson https://troydhanson.github.io/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* a dynamic string implementation using macros + */ +#ifndef UTSTRING_H +#define UTSTRING_H + +#define UTSTRING_VERSION 2.3.0 + +#include +#include +#include +#include + +#ifdef __GNUC__ +#define UTSTRING_UNUSED __attribute__((__unused__)) +#else +#define UTSTRING_UNUSED +#endif + +#ifdef oom +#error "The name of macro 'oom' has been changed to 'utstring_oom'. Please update your code." +#define utstring_oom() oom() +#endif + +#ifndef utstring_oom +#define utstring_oom() exit(-1) +#endif + +typedef struct { + char *d; /* pointer to allocated buffer */ + size_t n; /* allocated capacity */ + size_t i; /* index of first unused byte */ +} UT_string; + +#define utstring_reserve(s,amt) \ +do { \ + if (((s)->n - (s)->i) < (size_t)(amt)) { \ + char *utstring_tmp = (char*)realloc( \ + (s)->d, (s)->n + (amt)); \ + if (!utstring_tmp) { \ + utstring_oom(); \ + } \ + (s)->d = utstring_tmp; \ + (s)->n += (amt); \ + } \ +} while(0) + +#define utstring_init(s) \ +do { \ + (s)->n = 0; (s)->i = 0; (s)->d = NULL; \ + utstring_reserve(s,100); \ + (s)->d[0] = '\0'; \ +} while(0) + +#define utstring_done(s) \ +do { \ + if ((s)->d != NULL) free((s)->d); \ + (s)->n = 0; \ +} while(0) + +#define utstring_free(s) \ +do { \ + utstring_done(s); \ + free(s); \ +} while(0) + +#define utstring_new(s) \ +do { \ + (s) = (UT_string*)malloc(sizeof(UT_string)); \ + if (!(s)) { \ + utstring_oom(); \ + } \ + utstring_init(s); \ +} while(0) + +#define utstring_renew(s) \ +do { \ + if (s) { \ + utstring_clear(s); \ + } else { \ + utstring_new(s); \ + } \ +} while(0) + +#define utstring_clear(s) \ +do { \ + (s)->i = 0; \ + (s)->d[0] = '\0'; \ +} while(0) + +#define utstring_bincpy(s,b,l) \ +do { \ + utstring_reserve((s),(l)+1); \ + if (l) memcpy(&(s)->d[(s)->i], b, l); \ + (s)->i += (l); \ + (s)->d[(s)->i]='\0'; \ +} while(0) + +#define utstring_concat(dst,src) \ +do { \ + utstring_reserve((dst),((src)->i)+1); \ + if ((src)->i) memcpy(&(dst)->d[(dst)->i], (src)->d, (src)->i); \ + (dst)->i += (src)->i; \ + (dst)->d[(dst)->i]='\0'; \ +} while(0) + +#define utstring_len(s) ((s)->i) + +#define utstring_body(s) ((s)->d) + +UTSTRING_UNUSED static void utstring_printf_va(UT_string *s, const char *fmt, va_list ap) { + int n; + va_list cp; + for (;;) { +#ifdef _WIN32 + cp = ap; +#else + va_copy(cp, ap); +#endif + n = vsnprintf(&s->d[s->i], s->n-s->i, fmt, cp); + va_end(cp); + + if ((n > -1) && ((size_t) n < (s->n-s->i))) { + s->i += n; + return; + } + + /* Else try again with more space. */ + if (n > -1) utstring_reserve(s,n+1); /* exact */ + else utstring_reserve(s,(s->n)*2); /* 2x */ + } +} +#ifdef __GNUC__ +/* support printf format checking (2=the format string, 3=start of varargs) */ +static void utstring_printf(UT_string *s, const char *fmt, ...) + __attribute__((format(printf, 2, 3))); +#endif +UTSTRING_UNUSED static void utstring_printf(UT_string *s, const char *fmt, ...) { + va_list ap; + va_start(ap,fmt); + utstring_printf_va(s,fmt,ap); + va_end(ap); +} + +/******************************************************************************* + * begin substring search functions * + ******************************************************************************/ +/* Build KMP table from left to right. */ +UTSTRING_UNUSED static void _utstring_BuildTable( + const char *P_Needle, + size_t P_NeedleLen, + long *P_KMP_Table) +{ + long i, j; + + i = 0; + j = i - 1; + P_KMP_Table[i] = j; + while (i < (long) P_NeedleLen) + { + while ( (j > -1) && (P_Needle[i] != P_Needle[j]) ) + { + j = P_KMP_Table[j]; + } + i++; + j++; + if (i < (long) P_NeedleLen) + { + if (P_Needle[i] == P_Needle[j]) + { + P_KMP_Table[i] = P_KMP_Table[j]; + } + else + { + P_KMP_Table[i] = j; + } + } + else + { + P_KMP_Table[i] = j; + } + } + + return; +} + + +/* Build KMP table from right to left. */ +UTSTRING_UNUSED static void _utstring_BuildTableR( + const char *P_Needle, + size_t P_NeedleLen, + long *P_KMP_Table) +{ + long i, j; + + i = P_NeedleLen - 1; + j = i + 1; + P_KMP_Table[i + 1] = j; + while (i >= 0) + { + while ( (j < (long) P_NeedleLen) && (P_Needle[i] != P_Needle[j]) ) + { + j = P_KMP_Table[j + 1]; + } + i--; + j--; + if (i >= 0) + { + if (P_Needle[i] == P_Needle[j]) + { + P_KMP_Table[i + 1] = P_KMP_Table[j + 1]; + } + else + { + P_KMP_Table[i + 1] = j; + } + } + else + { + P_KMP_Table[i + 1] = j; + } + } + + return; +} + + +/* Search data from left to right. ( Multiple search mode. ) */ +UTSTRING_UNUSED static long _utstring_find( + const char *P_Haystack, + size_t P_HaystackLen, + const char *P_Needle, + size_t P_NeedleLen, + const long *P_KMP_Table) +{ + long i, j; + long V_FindPosition = -1; + + /* Search from left to right. */ + i = j = 0; + while ( (j < (int)P_HaystackLen) && (((P_HaystackLen - j) + i) >= P_NeedleLen) ) + { + while ( (i > -1) && (P_Needle[i] != P_Haystack[j]) ) + { + i = P_KMP_Table[i]; + } + i++; + j++; + if (i >= (int)P_NeedleLen) + { + /* Found. */ + V_FindPosition = j - i; + break; + } + } + + return V_FindPosition; +} + + +/* Search data from right to left. ( Multiple search mode. ) */ +UTSTRING_UNUSED static long _utstring_findR( + const char *P_Haystack, + size_t P_HaystackLen, + const char *P_Needle, + size_t P_NeedleLen, + const long *P_KMP_Table) +{ + long i, j; + long V_FindPosition = -1; + + /* Search from right to left. */ + j = (P_HaystackLen - 1); + i = (P_NeedleLen - 1); + while ( (j >= 0) && (j >= i) ) + { + while ( (i < (int)P_NeedleLen) && (P_Needle[i] != P_Haystack[j]) ) + { + i = P_KMP_Table[i + 1]; + } + i--; + j--; + if (i < 0) + { + /* Found. */ + V_FindPosition = j + 1; + break; + } + } + + return V_FindPosition; +} + + +/* Search data from left to right. ( One time search mode. ) */ +UTSTRING_UNUSED static long utstring_find( + const UT_string *s, + long P_StartPosition, /* Start from 0. -1 means last position. */ + const char *P_Needle, + size_t P_NeedleLen) +{ + long V_StartPosition; + long V_HaystackLen; + long *V_KMP_Table; + long V_FindPosition = -1; + + if (P_StartPosition < 0) + { + V_StartPosition = s->i + P_StartPosition; + } + else + { + V_StartPosition = P_StartPosition; + } + V_HaystackLen = s->i - V_StartPosition; + if ( (V_HaystackLen >= (long) P_NeedleLen) && (P_NeedleLen > 0) ) + { + V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1)); + if (V_KMP_Table != NULL) + { + _utstring_BuildTable(P_Needle, P_NeedleLen, V_KMP_Table); + + V_FindPosition = _utstring_find(s->d + V_StartPosition, + V_HaystackLen, + P_Needle, + P_NeedleLen, + V_KMP_Table); + if (V_FindPosition >= 0) + { + V_FindPosition += V_StartPosition; + } + + free(V_KMP_Table); + } + } + + return V_FindPosition; +} + + +/* Search data from right to left. ( One time search mode. ) */ +UTSTRING_UNUSED static long utstring_findR( + const UT_string *s, + long P_StartPosition, /* Start from 0. -1 means last position. */ + const char *P_Needle, + size_t P_NeedleLen) +{ + long V_StartPosition; + long V_HaystackLen; + long *V_KMP_Table; + long V_FindPosition = -1; + + if (P_StartPosition < 0) + { + V_StartPosition = s->i + P_StartPosition; + } + else + { + V_StartPosition = P_StartPosition; + } + V_HaystackLen = V_StartPosition + 1; + if ( (V_HaystackLen >= (long) P_NeedleLen) && (P_NeedleLen > 0) ) + { + V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1)); + if (V_KMP_Table != NULL) + { + _utstring_BuildTableR(P_Needle, P_NeedleLen, V_KMP_Table); + + V_FindPosition = _utstring_findR(s->d, + V_HaystackLen, + P_Needle, + P_NeedleLen, + V_KMP_Table); + + free(V_KMP_Table); + } + } + + return V_FindPosition; +} +/******************************************************************************* + * end substring search functions * + ******************************************************************************/ + +#endif /* UTSTRING_H */ diff --git a/src/ocre/ocre.c b/src/ocre/ocre.c new file mode 100644 index 00000000..b4854afd --- /dev/null +++ b/src/ocre/ocre.c @@ -0,0 +1,129 @@ +#include +#include +#include + +#include + +#include + +#include + +#include + +#include + +#include "commit_id.h" +#include "version.h" + +LOG_MODULE_REGISTER(ocre); + +/* Constant build information */ + +const struct ocre_config ocre_build_configuration = { + .build_info = OCRE_BUILD_HOST_INFO, + .version = OCRE_VERSION_STRING, + .commit_id = GIT_COMMIT_ID, +}; + +/* List of runtimes */ + +struct runtime_node { + const struct ocre_runtime_vtable *runtime; + struct runtime_node *next; +}; + +static struct runtime_node *runtimes = NULL; + +int ocre_initialize_with_runtimes(const struct ocre_runtime_vtable *const vtable[]) +{ + /* Add WAMR runtime to the list */ + + struct runtime_node *wamr = malloc(sizeof(struct runtime_node)); + if (!wamr) { + LOG_ERR("Failed to allocate memory for WAMR node"); + return -1; + } + + memset(wamr, 0, sizeof(struct runtime_node)); + wamr->runtime = &wamr_vtable; + + LL_APPEND(runtimes, wamr); + + /* Add extra runtimes */ + + if (vtable) { + for (int i = 0; vtable[i] != NULL; i++) { + struct runtime_node *add = malloc(sizeof(struct runtime_node)); + if (!add) { + LOG_ERR("Failed to allocate memory for runtime node"); + return -1; + } + + memset(add, 0, sizeof(struct runtime_node)); + add->runtime = (const struct ocre_runtime_vtable *)&vtable[i]; + + LL_APPEND(runtimes, add); + + LOG_INF("Registered '%s'", vtable[i]->runtime_name); + } + } + + /* Initialize runtimes in the list */ + + struct runtime_node *elt; + + LL_FOREACH(runtimes, elt) + { + if (elt->runtime->init && elt->runtime->init()) { + LOG_INF("Failed to initialize '%s'", elt->runtime->runtime_name); + return -1; + } + + LOG_INF("Initialized '%s'", elt->runtime->runtime_name); + } + + return 0; +} + +int ocre_initialize(void) +{ + LOG_INF("Initializing OCRE %s", ocre_build_configuration.version); + LOG_INF("Build Commit ID: %s", ocre_build_configuration.commit_id); + LOG_INF("Build Host: %s", ocre_build_configuration.build_info); + + return ocre_initialize_with_runtimes((const struct ocre_runtime_vtable *const[]){NULL}); +} + +const struct ocre_runtime_vtable *ocre_get_runtime(const char *name) +{ + if (!name) { + return NULL; + } + + struct runtime_node *elt; + + LL_FOREACH(runtimes, elt) + { + if (!strcmp(elt->runtime->runtime_name, name)) { + return elt->runtime; + } + } + + return NULL; +} + +void ocre_deinitialize(void) +{ + struct runtime_node *elt, *tmp; + + LL_FOREACH_SAFE(runtimes, elt, tmp) + { + if (elt->runtime->deinit && elt->runtime->deinit()) { + LOG_INF("Failed to deinitialize '%s'", elt->runtime->runtime_name); + } + + LL_DELETE(runtimes, elt); + + free(elt); + } +} diff --git a/src/ocre/ocre.h b/src/ocre/ocre.h index 0960403b..d47ac907 100644 --- a/src/ocre/ocre.h +++ b/src/ocre/ocre.h @@ -1,25 +1,3 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ +#include -#ifndef OCRE_H -#define OCRE_H - -#include "ocre_core_external.h" - -#ifdef CONFIG_OCRE_LOG_DEBUG -#define OCRE_LOG_LEVEL LOG_LEVEL_DBG -#elif CONFIG_OCRE_LOG_ERR -#define OCRE_LOG_LEVEL LOG_LEVEL_ERR -#elif CONFIG_OCRE_LOG_WARN -#define OCRE_LOG_LEVEL LOG_LEVEL_WRN -#elif CONFIG_OCRE_LOG_INF -#define OCRE_LOG_LEVEL LOG_LEVEL_INF -#else -#define OCRE_LOG_LEVEL LOG_LEVEL_NONE -#endif - -#endif +const struct ocre_runtime_vtable *ocre_get_runtime(const char *name); diff --git a/src/ocre/ocre_container_runtime/ocre_container_runtime.c b/src/ocre/ocre_container_runtime/ocre_container_runtime.c deleted file mode 100644 index ce3e7bea..00000000 --- a/src/ocre/ocre_container_runtime/ocre_container_runtime.c +++ /dev/null @@ -1,135 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include "ocre_core_external.h" -#include "../components/container_supervisor/cs_sm.h" -#include "../components/container_supervisor/cs_sm_impl.h" -// WAMR includes -// #include "coap_ext.h" -#include "../api/ocre_api.h" - -#include -#include - -LOG_MODULE_DECLARE(ocre_cs_component, OCRE_LOG_LEVEL); - -#include "ocre_container_runtime.h" - -ocre_container_runtime_status_t ocre_container_runtime_init(ocre_cs_ctx *ctx, ocre_container_init_arguments_t *args) { - // Zeroing the context - if (CS_runtime_init(ctx, args) != RUNTIME_STATUS_INITIALIZED) { - LOG_ERR("Failed to initialize container runtime"); - return RUNTIME_STATUS_ERROR; - } - - CS_ctx_init(ctx); - ctx->download_count = 0; - - start_ocre_cs_thread(ctx); - core_sleep_ms(1000); - return RUNTIME_STATUS_INITIALIZED; -} - -ocre_container_status_t ocre_container_runtime_destroy(void) { - wasm_runtime_destroy(); - destroy_ocre_cs_thread(); - return RUNTIME_STATUS_DESTROYED; -} - -ocre_container_status_t ocre_container_runtime_create_container(ocre_cs_ctx *ctx, ocre_container_data_t *container_data, - int *container_id, ocre_container_runtime_cb callback) { - int i; - uint8_t validity_flag = false; - // Find available slot for new container - for (i = 0; i < CONFIG_MAX_CONTAINERS; i++) { - if ((ctx->containers[i].container_runtime_status == CONTAINER_STATUS_UNKNOWN) || - (ctx->containers[i].container_runtime_status == CONTAINER_STATUS_DESTROYED)) { - *container_id = i; - ctx->containers[i].container_ID = i; - validity_flag = true; - break; - } - } - - if (validity_flag == false) { - LOG_ERR("No available slots, unable to create container"); - return CONTAINER_STATUS_ERROR; - } - LOG_INF("Request to create new container in slot: %d", *container_id); - - struct ocre_message event = {.event = EVENT_CREATE_CONTAINER}; - ocre_container_data_t Data; - event.containerId = *container_id; - Data = *container_data; - ctx->containers[*container_id].ocre_container_data = Data; - ctx->containers[*container_id].ocre_runtime_arguments.module_inst = NULL; - ctx->download_count++; - - ocre_component_send(&ocre_cs_component, &event); - return CONTAINER_STATUS_CREATED; -} - -ocre_container_status_t ocre_container_runtime_run_container(int container_id, ocre_container_runtime_cb callback) { - if (container_id < 0 || container_id >= CONFIG_MAX_CONTAINERS) { - LOG_ERR("Invalid container ID: %d", container_id); - return CONTAINER_STATUS_ERROR; - } - - LOG_INF("Request to run container in slot:%d", container_id); - struct ocre_message event = {.event = EVENT_RUN_CONTAINER}; - event.containerId = container_id; - ocre_component_send(&ocre_cs_component, &event); - return CONTAINER_STATUS_RUNNING; -} - -ocre_container_status_t ocre_container_runtime_get_container_status(ocre_cs_ctx *ctx, int container_id) { - if (container_id < 0 || container_id >= CONFIG_MAX_CONTAINERS) { - LOG_ERR("Invalid container ID: %d", container_id); - return CONTAINER_STATUS_ERROR; - } - - return ctx->containers[container_id].container_runtime_status; -} - -ocre_container_status_t ocre_container_runtime_stop_container(int container_id, ocre_container_runtime_cb callback) { - if (container_id < 0 || container_id >= CONFIG_MAX_CONTAINERS) { - LOG_ERR("Invalid container ID: %d", container_id); - return CONTAINER_STATUS_ERROR; - } - LOG_INF("Request to stop container in slot: %d", container_id); - struct ocre_message event = {.event = EVENT_STOP_CONTAINER}; - event.containerId = container_id; - ocre_component_send(&ocre_cs_component, &event); - return CONTAINER_STATUS_STOPPED; -} - -ocre_container_status_t ocre_container_runtime_destroy_container(ocre_cs_ctx *ctx, int container_id, - ocre_container_runtime_cb callback) { - if (container_id < 0 || container_id >= CONFIG_MAX_CONTAINERS) { - LOG_ERR("Invalid container ID: %d", container_id); - return CONTAINER_STATUS_ERROR; - } - LOG_INF("Request to destroy container in slot: %d", container_id); - struct ocre_message event = {.event = EVENT_DESTROY_CONTAINER}; - event.containerId = container_id; - ocre_component_send(&ocre_cs_component, &event); - return CONTAINER_STATUS_DESTROYED; -} - -ocre_container_status_t ocre_container_runtime_restart_container(ocre_cs_ctx *ctx, int container_id, - ocre_container_runtime_cb callback) { - if (container_id < 0 || container_id >= CONFIG_MAX_CONTAINERS) { - LOG_ERR("Invalid container ID: %d", container_id); - return CONTAINER_STATUS_ERROR; - } - LOG_INF("Request to restart container in slot: %d", container_id); - struct ocre_message event = {.event = EVENT_RESTART_CONTAINER}; - event.containerId = container_id; - ocre_component_send(&ocre_cs_component, &event); - return ctx->containers[container_id].container_runtime_status; -} diff --git a/src/ocre/ocre_container_runtime/ocre_container_runtime.h b/src/ocre/ocre_container_runtime/ocre_container_runtime.h deleted file mode 100644 index 2d1b46cd..00000000 --- a/src/ocre/ocre_container_runtime/ocre_container_runtime.h +++ /dev/null @@ -1,212 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef OCRE_CONTAINER_RUNTIME_H -#define OCRE_CONTAINER_RUNTIME_H - -#include - -#include "ocre_core_external.h" -#include "wasm_export.h" - -#define OCRE_CR_DEBUG_ON 0 // Debug flag for container runtime (0: OFF, 1: ON) -#define FILE_PATH_MAX 256 // Maximum file path length -#define OCRE_CR_INIT_TIMEOUT 500 // Timeout to wait for the container registry to initialize - - -/** - * @brief Structure containing the runtime arguments for a container runtime. - */ -typedef struct ocre_runtime_arguments_t { - uint32_t size; ///< Size of the buffer. - char *buffer; ///< Pointer to the buffer containing the WASM module. - char error_buf[128]; ///< Buffer to store error messages. - wasm_module_t module; ///< Handle to the loaded WASM module. - wasm_module_inst_t module_inst; ///< Handle to the instantiated WASM module. - wasm_function_inst_t func; ///< Handle to the function to be executed within the WASM module. - uint32_t stack_size; ///< Stack size for the WASM module. - uint32_t heap_size; ///< Heap size for the WASM module. -} ocre_runtime_arguments_t; - -/** - * @brief Enum representing the permission types for containers. - * NOT USED YET - */ -typedef enum { - OCRE_CONTAINER_PERM_READ_ONLY, ///< Container has read-only permissions. - OCRE_CONTAINER_PERM_READ_WRITE, ///< Container has read and write permissions. - OCRE_CONTAINER_PERM_EXECUTE ///< Container has execute permissions. -} ocre_container_permissions_t; - -/** - * @brief Enum representing the possible status of the container runtime - */ -typedef enum { - RUNTIME_STATUS_UNKNOWN, ///< Status is unknown. - RUNTIME_STATUS_INITIALIZED, ///< Runtime has been initialized. - RUNTIME_STATUS_DESTROYED, ///< Runtime has been destroyed - RUNTIME_STATUS_ERROR ///< An error occurred with the container. -} ocre_container_runtime_status_t; - -/** - * @brief Enum representing the possible status of a container. - */ -typedef enum { - CONTAINER_STATUS_UNKNOWN, ///< Status is unknown. - CONTAINER_STATUS_CREATED, ///< Container has been created. - CONTAINER_STATUS_RUNNING, ///< Container is currently running. - CONTAINER_STATUS_STOPPED, ///< Container has been stopped. - CONTAINER_STATUS_DESTROYED, ///< Container has been destroyed. - CONTAINER_STATUS_UNRESPONSIVE, ///< Container is unresponsive. -> For Healthcheck - CONTAINER_STATUS_ERROR, ///< An error occurred with the container. -} ocre_container_status_t; - -typedef struct ocre_container_runtime_init_arguments_t { - uint32_t default_stack_size; ///< Stack size for the WASM module. - uint32_t default_heap_size; ///< Heap size for the WASM module. - int maximum_containers; ///< Maximum number of containers allowed. - NativeSymbol *ocre_api_functions; -} ocre_container_init_arguments_t; - -/** - * @brief Structure representing the data associated with a container. - */ -typedef struct ocre_container_data_t { - char name[OCRE_MODULE_NAME_LEN]; // -#include "ocre_core_external.h" -#include -#include -#include - -LOG_MODULE_DECLARE(ocre_cs_component, OCRE_LOG_LEVEL); - -#ifndef CONFIG_MESSAGING_MAX_SUBSCRIPTIONS -#define CONFIG_MESSAGING_MAX_SUBSCRIPTIONS 10 -#endif -#define OCRE_MAX_TOPIC_LEN 64 - -/* Messaging subscription structure */ -typedef struct { - char topic[OCRE_MAX_TOPIC_LEN]; - wasm_module_inst_t module_inst; - bool is_active; -} ocre_messaging_subscription_t; - -typedef struct { - ocre_messaging_subscription_t subscriptions[CONFIG_MESSAGING_MAX_SUBSCRIPTIONS]; - uint16_t subscription_count; - core_mutex_t mutex; -} ocre_messaging_system_t; - -static ocre_messaging_system_t messaging_system = {0}; -static bool messaging_system_initialized = false; - -/* Initialize messaging system */ -int ocre_messaging_init(void) { - if (messaging_system_initialized) { - LOG_INF("Messaging system already initialized"); - return 0; - } - - if (!common_initialized && ocre_common_init() != 0) { - LOG_ERR("Failed to initialize common subsystem"); - return -EAGAIN; - } - - memset(&messaging_system, 0, sizeof(ocre_messaging_system_t)); - - core_mutex_init(&messaging_system.mutex); - - ocre_register_cleanup_handler(OCRE_RESOURCE_TYPE_MESSAGING, ocre_messaging_cleanup_container); - messaging_system_initialized = true; - LOG_INF("Messaging system initialized"); - return 0; -} - -/* Cleanup messaging resources for a module */ -void ocre_messaging_cleanup_container(wasm_module_inst_t module_inst) { - if (!messaging_system_initialized || !module_inst) { - return; - } - - core_mutex_lock(&messaging_system.mutex); - - for (int i = 0; i < CONFIG_MESSAGING_MAX_SUBSCRIPTIONS; i++) { - if (messaging_system.subscriptions[i].is_active && - messaging_system.subscriptions[i].module_inst == module_inst) { - messaging_system.subscriptions[i].is_active = false; - messaging_system.subscriptions[i].module_inst = NULL; - messaging_system.subscriptions[i].topic[0] = '\0'; - messaging_system.subscription_count--; - ocre_decrement_resource_count(module_inst, OCRE_RESOURCE_TYPE_MESSAGING); - LOG_DBG("Cleaned up subscription %d for module %p", i, (void *)module_inst); - } - } - - core_mutex_unlock(&messaging_system.mutex); - - LOG_DBG("Cleaned up messaging resources for module %p", (void *)module_inst); -} - -/* Subscribe to a topic */ -int ocre_messaging_subscribe(wasm_exec_env_t exec_env, void *topic) { - if (!messaging_system_initialized) { - if (ocre_messaging_init() != 0) { - LOG_ERR("Failed to initialize messaging system"); - return -EINVAL; - } - } - - if (!topic || ((char *)topic)[0] == '\0') { - LOG_ERR("Topic is NULL or empty"); - return -EINVAL; - } - - wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); - if (!module_inst) { - LOG_ERR("No module instance for exec_env"); - return -EINVAL; - } - - ocre_module_context_t *ctx = ocre_get_module_context(module_inst); - if (!ctx) { - LOG_ERR("Module context not found for module instance %p", (void *)module_inst); - return -EINVAL; - } - - core_mutex_lock(&messaging_system.mutex); - - // Check if already subscribed - for (int i = 0; i < CONFIG_MESSAGING_MAX_SUBSCRIPTIONS; i++) { - if (messaging_system.subscriptions[i].is_active && - messaging_system.subscriptions[i].module_inst == module_inst && - strcmp(messaging_system.subscriptions[i].topic, (char *)topic) == 0) { - LOG_INF("Already subscribed to topic: %s", (char *)topic); - core_mutex_unlock(&messaging_system.mutex); - return 0; - } - } - - // Find a free slot - for (int i = 0; i < CONFIG_MESSAGING_MAX_SUBSCRIPTIONS; i++) { - if (!messaging_system.subscriptions[i].is_active) { - strncpy(messaging_system.subscriptions[i].topic, (char *)topic, OCRE_MAX_TOPIC_LEN - 1); - messaging_system.subscriptions[i].topic[OCRE_MAX_TOPIC_LEN - 1] = '\0'; - messaging_system.subscriptions[i].module_inst = module_inst; - messaging_system.subscriptions[i].is_active = true; - messaging_system.subscription_count++; - ocre_increment_resource_count(module_inst, OCRE_RESOURCE_TYPE_MESSAGING); - LOG_INF("Subscribed to topic: %s, module: %p", (char *)topic, (void *)module_inst); - core_mutex_unlock(&messaging_system.mutex); - return 0; - } - } - - core_mutex_unlock(&messaging_system.mutex); - - LOG_ERR("No free subscription slots available"); - return -ENOMEM; -} - -/* Publish a message */ -int ocre_messaging_publish(wasm_exec_env_t exec_env, void *topic, void *content_type, void *payload, int payload_len) { - if (!messaging_system_initialized) { - if (ocre_messaging_init() != 0) { - LOG_ERR("Failed to initialize messaging system"); - return -EINVAL; - } - } - - if (!topic || ((char *)topic)[0] == '\0') { - LOG_ERR("Topic is NULL or empty"); - return -EINVAL; - } - if (!content_type || ((char *)content_type)[0] == '\0') { - LOG_ERR("Content type is NULL or empty"); - return -EINVAL; - } - if (!payload || payload_len <= 0) { - LOG_ERR("Payload is NULL or payload_len is invalid"); - return -EINVAL; - } - - wasm_module_inst_t publisher_module = wasm_runtime_get_module_inst(exec_env); - if (!publisher_module) { - LOG_ERR("No module instance for exec_env"); - return -EINVAL; - } - - static uint32_t message_id = 0; - bool message_sent = false; - - core_mutex_lock(&messaging_system.mutex); - - // Find matching subscriptions - for (int i = 0; i < CONFIG_MESSAGING_MAX_SUBSCRIPTIONS; i++) { - if (!messaging_system.subscriptions[i].is_active) { - continue; - } - - // Check if the published topic matches the subscription (prefix match) - const char *subscribed_topic = messaging_system.subscriptions[i].topic; - size_t subscribed_len = strlen(subscribed_topic); - - if (strncmp(subscribed_topic, (char *)topic, subscribed_len) != 0) { - continue; // No prefix match - } - - wasm_module_inst_t target_module = messaging_system.subscriptions[i].module_inst; - if (!target_module) { - LOG_ERR("Invalid module instance for subscription %d", i); - continue; - } - - // Allocate WASM memory for the target module - uint32_t topic_offset = (uint32_t)wasm_runtime_module_dup_data(target_module, (char *)topic, strlen((char *)topic) + 1); - if (topic_offset == 0) { - LOG_ERR("Failed to allocate WASM memory for topic"); - continue; - } - - uint32_t content_offset = (uint32_t)wasm_runtime_module_dup_data(target_module, (char *)content_type, strlen((char *)content_type) + 1); - if (content_offset == 0) { - LOG_ERR("Failed to allocate WASM memory for content_type"); - wasm_runtime_module_free(target_module, topic_offset); - continue; - } - - uint32_t payload_offset = (uint32_t)wasm_runtime_module_dup_data(target_module, payload, payload_len); - if (payload_offset == 0) { - LOG_ERR("Failed to allocate WASM memory for payload"); - wasm_runtime_module_free(target_module, topic_offset); - wasm_runtime_module_free(target_module, content_offset); - continue; - } - - // Create and queue the messaging event - ocre_event_t event; - event.type = OCRE_RESOURCE_TYPE_MESSAGING; - event.data.messaging_event.message_id = message_id; - event.data.messaging_event.topic = topic; - event.data.messaging_event.topic_offset = topic_offset; - event.data.messaging_event.content_type = content_type; - event.data.messaging_event.content_type_offset = content_offset; - event.data.messaging_event.payload = payload; - event.data.messaging_event.payload_offset = payload_offset; - event.data.messaging_event.payload_len = (uint32_t)payload_len; - event.owner = target_module; - - LOG_DBG("Creating messaging event: ID=%d, topic=%s, content_type=%s, payload_len=%d for module %p", - message_id, (char *)topic, (char *)content_type, payload_len, (void *)target_module); - - core_spinlock_key_t key = core_spinlock_lock(&ocre_event_queue_lock); - if (core_eventq_put(&ocre_event_queue, &event) != 0) { - LOG_ERR("Failed to queue messaging event for message ID %d", message_id); - wasm_runtime_module_free(target_module, topic_offset); - wasm_runtime_module_free(target_module, content_offset); - wasm_runtime_module_free(target_module, payload_offset); - } else { - message_sent = true; - LOG_DBG("Queued messaging event for message ID %d", message_id); - } - core_spinlock_unlock(&ocre_event_queue_lock, key); - } - - core_mutex_unlock(&messaging_system.mutex); - - if (message_sent) { - LOG_DBG("Published message: ID=%d, topic=%s, content_type=%s, payload_len=%d", - message_id, (char *)topic, (char *)content_type, payload_len); - message_id++; - return 0; - } else { - LOG_WRN("No matching subscriptions found for topic %s", (char *)topic); - return -ENOENT; - } -} - -/* Free module event data */ -int ocre_messaging_free_module_event_data(wasm_exec_env_t exec_env, uint32_t topic_offset, uint32_t content_offset, uint32_t payload_offset) { - wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); - if (!module_inst) { - LOG_ERR("Cannot find module_inst for free event data"); - return -EINVAL; - } - - wasm_runtime_module_free(module_inst, topic_offset); - wasm_runtime_module_free(module_inst, content_offset); - wasm_runtime_module_free(module_inst, payload_offset); - - return 0; -} diff --git a/src/ocre/ocre_timers/ocre_timer.c b/src/ocre/ocre_timers/ocre_timer.c deleted file mode 100644 index 02a67d91..00000000 --- a/src/ocre/ocre_timers/ocre_timer.c +++ /dev/null @@ -1,255 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre, a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include - -#include -#include -#include -#include -#include - -LOG_MODULE_DECLARE(ocre_cs_component, OCRE_LOG_LEVEL); - -/* Unified timer structure using core_timer API */ -typedef struct { - uint32_t in_use: 1; - uint32_t id: 8; // Up to 256 timers - uint32_t interval: 16; // Up to 65s intervals - uint32_t periodic: 1; - uint32_t running: 1; // Track if timer is currently running - uint32_t start_time; // Start time for remaining time calculations - core_timer_t timer; // Unified core timer - wasm_module_inst_t owner; -} ocre_timer_internal; - -#ifndef CONFIG_MAX_TIMERS -#define CONFIG_MAX_TIMERS 5 -#endif - -// Static data -static ocre_timer_internal timers[CONFIG_MAX_TIMERS]; -static bool timer_system_initialized = false; - -static void unified_timer_callback(void *user_data); - -void ocre_timer_init(void) { - if (timer_system_initialized) { - LOG_INF("Timer system already initialized"); - return; - } - - if (!common_initialized && ocre_common_init() != 0) { - LOG_ERR("Failed to initialize common subsystem"); - return; - } - - ocre_register_cleanup_handler(OCRE_RESOURCE_TYPE_TIMER, ocre_timer_cleanup_container); - timer_system_initialized = true; - LOG_INF("Timer system initialized"); -} - -int ocre_timer_create(wasm_exec_env_t exec_env, int id) { - wasm_module_inst_t module = wasm_runtime_get_module_inst(exec_env); - if (!module || id <= 0 || id > CONFIG_MAX_TIMERS) { - LOG_ERR("Invalid module %p or timer ID %d (max: %d)", (void *)module, id, CONFIG_MAX_TIMERS); - return -EINVAL; - } - - ocre_timer_internal *timer = &timers[id - 1]; - if (timer->in_use) { - LOG_ERR("Timer ID %d already in use", id); - return -EBUSY; - } - - timer->id = id; - timer->owner = module; - timer->in_use = 1; - - // Initialize unified core timer - if (core_timer_init(&timer->timer, unified_timer_callback, timer) != 0) { - LOG_ERR("Failed to initialize core timer %d", id); - timer->in_use = 0; - return -EINVAL; - } - - ocre_increment_resource_count(module, OCRE_RESOURCE_TYPE_TIMER); - LOG_INF("Created timer %d for module %p", id, (void *)module); - return 0; -} - -int ocre_timer_delete(wasm_exec_env_t exec_env, ocre_timer_t id) { - wasm_module_inst_t module = wasm_runtime_get_module_inst(exec_env); - if (!module || id <= 0 || id > CONFIG_MAX_TIMERS) { - LOG_ERR("Invalid module %p or timer ID %d", (void *)module, id); - return -EINVAL; - } - - ocre_timer_internal *timer = &timers[id - 1]; - if (!timer->in_use || timer->owner != module) { - LOG_ERR("Timer ID %d not in use or not owned by module %p", id, (void *)module); - return -EINVAL; - } - - // Stop unified core timer - core_timer_stop(&timer->timer); - - timer->in_use = 0; - timer->running = 0; - timer->owner = NULL; - ocre_decrement_resource_count(module, OCRE_RESOURCE_TYPE_TIMER); - LOG_INF("Deleted timer %d", id); - return 0; -} - -int ocre_timer_start(wasm_exec_env_t exec_env, ocre_timer_t id, int interval, int is_periodic) { - wasm_module_inst_t module = wasm_runtime_get_module_inst(exec_env); - if (!module || id <= 0 || id > CONFIG_MAX_TIMERS) { - LOG_ERR("Invalid module %p or timer ID %d", (void *)module, id); - return -EINVAL; - } - - ocre_timer_internal *timer = &timers[id - 1]; - if (!timer->in_use || timer->owner != module) { - LOG_ERR("Timer ID %d not in use or not owned by module %p", id, (void *)module); - return -EINVAL; - } - - if (interval <= 0 || interval > 65535) { - LOG_ERR("Invalid interval %dms (must be 1-65535ms)", interval); - return -EINVAL; - } - - timer->interval = interval; - timer->periodic = is_periodic; - timer->start_time = core_uptime_get(); - timer->running = 1; - - // Start unified core timer - int period_ms = is_periodic ? interval : 0; - if (core_timer_start(&timer->timer, interval, period_ms) != 0) { - LOG_ERR("Failed to start core timer %d", id); - timer->running = 0; - return -EINVAL; - } - - LOG_INF("Started timer %d with interval %dms, periodic=%d", id, interval, is_periodic); - return 0; -} - -int ocre_timer_stop(wasm_exec_env_t exec_env, ocre_timer_t id) { - wasm_module_inst_t module = wasm_runtime_get_module_inst(exec_env); - if (!module || id <= 0 || id > CONFIG_MAX_TIMERS) { - LOG_ERR("Invalid module %p or timer ID %d", (void *)module, id); - return -EINVAL; - } - - ocre_timer_internal *timer = &timers[id - 1]; - if (!timer->in_use || timer->owner != module) { - LOG_ERR("Timer ID %d not in use or not owned by module %p", id, (void *)module); - return -EINVAL; - } - - // Stop unified core timer - core_timer_stop(&timer->timer); - timer->running = 0; - - LOG_INF("Stopped timer %d", id); - return 0; -} - -int ocre_timer_get_remaining(wasm_exec_env_t exec_env, ocre_timer_t id) { - wasm_module_inst_t module = wasm_runtime_get_module_inst(exec_env); - if (!module || id <= 0 || id > CONFIG_MAX_TIMERS) { - LOG_ERR("Invalid module %p or timer ID %d", (void *)module, id); - return -EINVAL; - } - - ocre_timer_internal *timer = &timers[id - 1]; - if (!timer->in_use || timer->owner != module) { - LOG_ERR("Timer ID %d not in use or not owned by module %p", id, (void *)module); - return -EINVAL; - } - - int remaining; - if (!timer->running) { - remaining = 0; - } else { - uint32_t current_time = core_uptime_get(); - uint32_t elapsed = current_time - timer->start_time; - if (elapsed >= timer->interval) { - remaining = 0; // Timer should have expired - } else { - remaining = timer->interval - elapsed; - } - } - - LOG_INF("Timer %d remaining time: %dms", id, remaining); - return remaining; -} - -void ocre_timer_cleanup_container(wasm_module_inst_t module_inst) { - if (!module_inst) { - LOG_ERR("Invalid module instance for cleanup"); - return; - } - - for (int i = 0; i < CONFIG_MAX_TIMERS; i++) { - if (timers[i].in_use && timers[i].owner == module_inst) { - // Stop unified core timer - core_timer_stop(&timers[i].timer); - timers[i].in_use = 0; - timers[i].running = 0; - timers[i].owner = NULL; - ocre_decrement_resource_count(module_inst, OCRE_RESOURCE_TYPE_TIMER); - LOG_DBG("Cleaned up timer %d for module %p", i + 1, (void *)module_inst); - } - } - LOG_DBG("Cleaned up timer resources for module %p", (void *)module_inst); -} - -/* Unified timer callback using core_timer API */ -static void unified_timer_callback(void *user_data) { - if (!timer_system_initialized || !common_initialized || !ocre_event_queue_initialized) { - LOG_ERR("Timer, common, or event queue not initialized, skipping callback"); - return; - } - - ocre_timer_internal *timer = (ocre_timer_internal *)user_data; - if (!timer || !timer->in_use || !timer->owner) { - LOG_ERR("Invalid timer in callback: %p", (void *)timer); - return; - } - - LOG_DBG("Timer callback for timer %d", timer->id); - - // For non-periodic timers, mark as not running - if (!timer->periodic) { - timer->running = 0; - } else { - // For periodic timers, update start time for next cycle - timer->start_time = core_uptime_get(); - } - - // Create and queue timer event - ocre_event_t event; - event.type = OCRE_RESOURCE_TYPE_TIMER; - event.data.timer_event.timer_id = timer->id; - event.owner = timer->owner; - - LOG_DBG("Creating timer event: type=%d, id=%d, for owner %p", event.type, timer->id, (void *)timer->owner); - - core_spinlock_key_t key = core_spinlock_lock(&ocre_event_queue_lock); - if (core_eventq_put(&ocre_event_queue, &event) != 0) { - LOG_ERR("Failed to queue timer event for timer %d", timer->id); - } else { - LOG_DBG("Queued timer event for timer %d", timer->id); - } - core_spinlock_unlock(&ocre_event_queue_lock, key); -} diff --git a/src/ocre/shell/ocre_shell.c b/src/ocre/shell/ocre_shell.c deleted file mode 100644 index 801b2193..00000000 --- a/src/ocre/shell/ocre_shell.c +++ /dev/null @@ -1,152 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -#include "ocre_shell.h" - -static ocre_cs_ctx *ctx_internal; - -int cmd_ocre_run(const struct shell *shell, size_t argc, char **argv) { - if (!ctx_internal) { - shell_error(shell, "Internal context not initialized."); - return -1; - } - - if (argc != 2) { - shell_error(shell, "Usage: ocre run "); - return -EINVAL; - } - - char *endptr; - int container_id = (int)strtol(argv[1], &endptr, 10); - - if (endptr == argv[1]) { - shell_error(shell, "No digits were found in argument .\n"); - return -EINVAL; - } else if (*endptr != '\0') { - shell_error(shell, "Invalid character: %c\n", *endptr); - return -EINVAL; - } - - int ret = -1; - for (int i = 0; i < CONFIG_MAX_CONTAINERS; i++) { - if (container_id == ctx_internal->containers[i].container_ID) { - ret = ocre_container_runtime_run_container(container_id, NULL); - break; - } - } - - if (ret == CONTAINER_STATUS_RUNNING) { - shell_info(shell, "Container started. Name: %s, ID: %d", - ctx_internal->containers[container_id].ocre_container_data.name, container_id); - return 0; - } else { - shell_error(shell, "Failed to run container: %d", container_id); - return -EIO; - } -} - -int cmd_ocre_stop(const struct shell *shell, size_t argc, char **argv) { - if (!ctx_internal) { - shell_error(shell, "Internal context not initialized."); - return -1; - } - - if (argc != 2) { - shell_error(shell, "Usage: ocre stop "); - return -EINVAL; - } - - const char *name = argv[1]; - shell_info(shell, "OCRE Shell Request to stop container with name: %s", name); - - int ret = -1; - int container_id = -1; - for (int i = 0; i < CONFIG_MAX_CONTAINERS; i++) { - if (strcmp(ctx_internal->containers[i].ocre_container_data.name, name) == 0) { - container_id = ctx_internal->containers[i].container_ID; - ret = ocre_container_runtime_stop_container(container_id, NULL); - } - } - - if (ret == CONTAINER_STATUS_STOPPED) { - shell_info(shell, "Container stopped. Name: %s, ID: %d", name, container_id); - } else if (ret == -1) { - shell_error(shell, "Failed to found container: %s", name); - } else { - shell_error(shell, "Failed to stop container: %s", name); - } - - return ret; -} - -int cmd_ocre_restart(const struct shell *shell, size_t argc, char **argv) { - if (!ctx_internal) { - shell_error(shell, "Internal context not initialized."); - return -1; - } - - if (argc != 2) { - shell_error(shell, "Usage: ocre restart "); - return -EINVAL; - } - - const char *name = argv[1]; - shell_info(shell, "OCRE Shell Request to restart container with name: %s", name); - - int ret = -1; - int container_id = -1; - for (int i = 0; i < CONFIG_MAX_CONTAINERS; i++) { - if (strcmp(ctx_internal->containers[i].ocre_container_data.name, name) == 0) { - container_id = ctx_internal->containers[i].container_ID; - ret = ocre_container_runtime_restart_container(ctx_internal, container_id, NULL); - } - } - - if (ret == CONTAINER_STATUS_RUNNING) { - shell_info(shell, "Container restarted. Name: %s, ID: %d", name, container_id); - } else if (ret == -1) { - shell_error(shell, "Failed to found container: %s", name); - } else { - shell_error(shell, "Failed to restart container: %s, status: %d", name, ret); - } - - return ret; -} - -int cmd_ocre_ls(const struct shell *shell, size_t argc, char **argv) { - ARG_UNUSED(argc); - ARG_UNUSED(argv); - - if (!ctx_internal) { - shell_error(shell, "Internal context not initialized."); - return -1; - } - - for (int i = 0; i < CONFIG_MAX_CONTAINERS; i++) { - shell_info(shell, "Container ID: %d, name: %s, status: %d", ctx_internal->containers[i].container_ID, - ctx_internal->containers[i].ocre_container_data.name, - ctx_internal->containers[i].container_runtime_status); - } - - return 0; -} - -void register_ocre_shell(ocre_cs_ctx *ctx) { - ctx_internal = ctx; - - SHELL_STATIC_SUBCMD_SET_CREATE( - ocre_subcmds, SHELL_CMD(run, NULL, "Start a new container: ocre run ", cmd_ocre_run), - SHELL_CMD(stop, NULL, "Stop a container: ocre stop ", cmd_ocre_stop), - SHELL_CMD(restart, NULL, "Restart a container: ocre restart ", cmd_ocre_restart), - SHELL_CMD(ls, NULL, "List running containers and their status", cmd_ocre_ls), SHELL_SUBCMD_SET_END); - -#if defined(CONFIG_OCRE_SHELL) - SHELL_CMD_REGISTER(ocre, &ocre_subcmds, "OCRE agent commands", NULL); -#endif -} diff --git a/src/ocre/shell/ocre_shell.h b/src/ocre/shell/ocre_shell.h deleted file mode 100644 index 3bb0bb81..00000000 --- a/src/ocre/shell/ocre_shell.h +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef OCRE_SHELL_H -#define OCRE_SHELL_H - -#include -#include "../src/ocre/ocre_container_runtime/ocre_container_runtime.h" - -// Function declarations for `config` subcommand handlers -int cmd_ocre_run(const struct shell *shell, size_t argc, char **argv); -int cmd_ocre_stop(const struct shell *shell, size_t argc, char **argv); -int cmd_ocre_ps(const struct shell *shell, size_t argc, char **argv); - -// Command registration function -void register_ocre_shell(ocre_cs_ctx *ctx); - -#endif /* OCRE_SHELL_H */ diff --git a/src/ocre/sm/sm.c b/src/ocre/sm/sm.c deleted file mode 100644 index 4c0068a2..00000000 --- a/src/ocre/sm/sm.c +++ /dev/null @@ -1,94 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include "ocre_core_external.h" -#include "ocre/component/component.h" - -#include -#include -#include - -#include "sm.h" -LOG_MODULE_REGISTER(state_machine, OCRE_LOG_LEVEL); - -void sm_init(state_machine_t *sm, core_mq_t *msgq, void *msg, void *custom_ctx, const struct smf_state *hsm) { - sm->hsm = hsm; - sm->msgq = msgq; - sm->ctx.event.msg = msg; - sm->ctx.custom_ctx = custom_ctx; -} - -int sm_run(state_machine_t *sm, int initial_state) { - int ret; - - smf_set_initial(SMF_CTX(&sm->ctx), &sm->hsm[initial_state]); - - while (true) { - // Wait for a message from the queue - core_mq_recv(sm->msgq, sm->ctx.event.msg); - sm->ctx.event.handled = false; - - ret = smf_run_state(SMF_CTX(&sm->ctx)); - - if (ret) { - LOG_ERR("State machine error: %d", ret); - break; - } - - if (!sm->ctx.event.handled) { - struct ocre_message const *msg = SM_GET_EVENT(&sm->ctx); - LOG_ERR("Unhandled event: msg type or data = %d", msg->event); - } - - // Yield the current thread to allow the queue events to be processed - core_yield(); - } - - return ret; -} - -int sm_transition(state_machine_t *sm, int target_state) { - if (!sm->hsm) { - LOG_ERR("State machine has not been initialized"); - return -EINVAL; - } - - smf_set_state(SMF_CTX(&sm->ctx), &sm->hsm[target_state]); - - return 0; -} - -int sm_init_event_timer(state_machine_t *sm, int timer_id, void *timer_cb) { - if (timer_id < 0 || timer_id >= MAX_TIMERS) { - LOG_ERR("Invalid timer id: %d", timer_id); - return -EINVAL; - } - - core_timer_init(&sm->timers[timer_id], timer_cb, NULL); - return 0; -} - -int sm_set_event_timer(state_machine_t *sm, int timer_id, int duration, int period) { - if (timer_id < 0 || timer_id >= MAX_TIMERS) { - LOG_ERR("Invalid timer id: %d", timer_id); - return -EINVAL; - } - - core_timer_start(&sm->timers[timer_id], duration, period); - return 0; -} - -int sm_clear_event_timer(state_machine_t *sm, int timer_id) { - if (timer_id < 0 || timer_id >= MAX_TIMERS) { - LOG_ERR("Invalid timer id: %d", timer_id); - return -EINVAL; - } - - core_timer_stop(&sm->timers[timer_id]); - return 0; -} diff --git a/src/ocre/sm/sm.h b/src/ocre/sm/sm.h deleted file mode 100644 index f2fd9803..00000000 --- a/src/ocre/sm/sm.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef SM_H -#define SM_H - -#include "ocre_core_external.h" - -#define MAX_TIMERS 3 - -#define SM_RETURN_IF_EVENT_HANDLED(o) \ - if (((struct sm_ctx *)o)->event.handled) \ - return SMF_EVENT_HANDLED -#define SM_MARK_EVENT_HANDLED(o) ((struct sm_ctx *)o)->event.handled = true -#define SM_GET_EVENT(o) ((struct sm_ctx *)o)->event.msg -#define SM_GET_CUSTOM_CTX(o) ((struct sm_ctx *)o)->custom_ctx - -#define EVENT_LOG_MSG(fmt, event) LOG_DBG(fmt, event) - -struct sm_ctx { - struct smf_ctx ctx; - struct { - bool handled; - void *msg; - } event; - void *custom_ctx; -}; - -typedef struct state_machine { - core_mq_t *msgq; - core_timer_t timers[MAX_TIMERS]; - struct sm_ctx ctx; /*!< State machine context */ - const struct smf_state *hsm; /*!< State machine states */ -} state_machine_t; - -int sm_transition(state_machine_t *sm, int target_state); - -int sm_run(state_machine_t *sm, int initial_state); - -int sm_init_event_timer(state_machine_t *sm, int timer_id, void *timer_cb); - -int sm_set_event_timer(state_machine_t *sm, int timer_id, int duration, int period); - -int sm_clear_event_timer(state_machine_t *sm, int timer_id); - -int sm_dispatch_event(state_machine_t *sm, void *msg); - -void sm_init(state_machine_t *sm, core_mq_t *msgq, void *msg, void *custom_ctx, const struct smf_state *hsm); - -#endif // SM_H diff --git a/src/ocre/unique_random_id.c b/src/ocre/unique_random_id.c new file mode 100644 index 00000000..d10e2520 --- /dev/null +++ b/src/ocre/unique_random_id.c @@ -0,0 +1,47 @@ +#include +#include + +#include "context.h" + +#include "unique_random_id.h" + +static char nibble_to_hex(char nibble) +{ + return nibble < 10 ? '0' + nibble : 'a' + nibble - 10; +} + +static void generate_random_id(char *id, size_t len) +{ + if (len < 1) { + return; + } + + size_t i; + for (i = 0; i < len - 1; i++) { + id[i] = nibble_to_hex(0xf & rand() / (RAND_MAX / 16)); + } + + id[i] = '\0'; +} + +int make_unique_random_container_id(const struct ocre_context *context, char *container_id, size_t len) +{ + char *random_id = malloc(len); + if (!random_id) { + return -1; + } + + for (int i = 0; i < 100; i++) { + generate_random_id(random_id, len); + if (!ocre_context_get_container_by_id_locked(context, random_id)) { + strcpy(container_id, random_id); + free(random_id); + return 0; + } + } + + /* Gave up */ + free(random_id); + + return -1; +} diff --git a/src/ocre/unique_random_id.h b/src/ocre/unique_random_id.h new file mode 100644 index 00000000..b6b389d5 --- /dev/null +++ b/src/ocre/unique_random_id.h @@ -0,0 +1,3 @@ +#include + +int make_unique_random_container_id(const struct ocre_context *context, char *container_id, size_t len); diff --git a/src/ocre/util/string_array.c b/src/ocre/util/string_array.c new file mode 100644 index 00000000..af6e0d46 --- /dev/null +++ b/src/ocre/util/string_array.c @@ -0,0 +1,109 @@ +#include +#include +#include + +#include "string_array.h" + +// returns the size of a string array including the NULL termination +// returns 0 if pointer is null +size_t string_array_size(const char **array) +{ + size_t size = 0; + + if (!array) { + return 0; + } + + do { + size++; + } while (*array++); + + return size; +} + +// duplicates an array of char * +// returns NULL on error +char **string_array_dup(char **src) +{ + size_t size = string_array_size((const char **)src); + + if (!size) { + return NULL; + } + + char **dst = malloc(size * sizeof(char *)); + if (!dst) { + return NULL; + } + + memset(dst, 0, size * sizeof(char *)); + + size_t i; + for (i = 0; i < size; i++) { + dst[i] = src[i]; + } + + return dst; +} + +void string_array_free(char **array) +{ + if (!array) { + return; + } + + for (size_t j = 0; array[j]; j++) { + free(array[j]); + } + + free(array); +} + +// makes a deep copy of an array of char * +// returns NULL on error +char **string_array_deep_dup(const char **const src) +{ + size_t size = string_array_size((const char **)src); + + if (!size) { + return NULL; + } + + char **dst = malloc(size * sizeof(char *)); + if (!dst) { + return NULL; + } + + memset(dst, 0, size * sizeof(char *)); + + size_t i; + for (i = 0; i < size - 1; i++) { + dst[i] = strdup(src[i]); + if (!dst[i]) { + goto error; + } + } + + dst[i] = NULL; + + return dst; + +error: + string_array_free(dst); + + return NULL; +} + +size_t string_array_copy(char **dest, char **src) +{ + if (!dest || !src) { + return 0; + } + + size_t count = 0; + do { + dest[count] = src[count]; + } while (src[count]); + + return count; +} diff --git a/src/ocre/util/string_array.h b/src/ocre/util/string_array.h new file mode 100644 index 00000000..d4ca2182 --- /dev/null +++ b/src/ocre/util/string_array.h @@ -0,0 +1,6 @@ +#include +size_t string_array_size(const char **const array); +char **string_array_dup(char **src); +char **string_array_deep_dup(const char **const src); +void string_array_free(char **array); +size_t string_array_copy(char **dest, char **src); diff --git a/src/ocre/utils/c-smf/CMakeLists.txt b/src/ocre/utils/c-smf/CMakeLists.txt deleted file mode 100644 index da453ef4..00000000 --- a/src/ocre/utils/c-smf/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -cmake_minimum_required(VERSION 3.20) -project(smf LANGUAGES C) - -set(CMAKE_C_STANDARD 99) -set(CMAKE_C_STANDARD_REQUIRED ON) -set(CMAKE_C_EXTENSIONS OFF) - -option(BUILD_TESTS "Build test program" OFF) - -add_subdirectory(smf) - -if(BUILD_TESTS) - add_subdirectory(test) - target_link_libraries(test smf) -endif(BUILD_TESTS) diff --git a/src/ocre/utils/c-smf/LICENSE b/src/ocre/utils/c-smf/LICENSE deleted file mode 100644 index 261eeb9e..00000000 --- a/src/ocre/utils/c-smf/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/src/ocre/utils/c-smf/README.md b/src/ocre/utils/c-smf/README.md deleted file mode 100644 index 66db56ed..00000000 --- a/src/ocre/utils/c-smf/README.md +++ /dev/null @@ -1,61 +0,0 @@ -# c-smf - -## Overview -Platform-independent port of the Zephyr Real-Time Operating System (RTOS) State Machine Framework. - -## Features -Easy integration with CMake. - -Utilizes the powerful Zephyr State Machine Framework for efficient state management. - -Apache 2.0 licensed for open-source use. - -## Getting Started - -1. Clone the repository -``` -git clone https://github.com/kr-t/c-smf.git -``` - -2. Add the new directory to your CMake project and link smf library to your executable -``` -add_subdirectory(c-smf) -target_link_libraries(... smf) -``` - -3. Include the State Machine Framework in your code -``` -#include "smf/smf.h" -``` - -## Example - -Simple stand-alone example is available in /test folder. To build it, use BUILD_TESTS option. -``` -mkdir build && cd build -cmake -DBUILD_TESTS=ON .. -make -./test/test -``` - -Output: -``` -Entering State 1 -Starting State Machine -Running State 1 -Transitioning to State 2 -Exiting State 1 -Entering State 2 -Running State 2 -State Machine Test Complete -``` - -For more information, you can refer to the official Zephyr RTOS documentation for the State Machine Framework: [Zephyr SMF Documentation](https://docs.zephyrproject.org/latest/services/smf/index.html) - -## License -This project is licensed under the Apache License 2.0 - see the LICENSE file for details. - -## Acknowledments -This project is ported from Zephyr Real-Time Operating System. - -Thanks to the open-source community for their contributions. diff --git a/src/ocre/utils/c-smf/smf/CMakeLists.txt b/src/ocre/utils/c-smf/smf/CMakeLists.txt deleted file mode 100644 index d3098178..00000000 --- a/src/ocre/utils/c-smf/smf/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -add_library(smf STATIC - smf.c -) - -set_target_properties(smf PROPERTIES PUBLIC_HEADER smf.h) -target_include_directories(smf PUBLIC ..) - -target_compile_options(smf PRIVATE - -fdiagnostics-color=always - -pedantic-errors - -Wall - -Wextra - -Wconversion - -Wsign-conversion - -Werror -) diff --git a/src/ocre/utils/c-smf/smf/smf.c b/src/ocre/utils/c-smf/smf/smf.c deleted file mode 100644 index dde5bbce..00000000 --- a/src/ocre/utils/c-smf/smf/smf.c +++ /dev/null @@ -1,421 +0,0 @@ -/* - * Copyright 2021 The Chromium OS Authors - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include - -#include "smf.h" - -/** - * @brief Private structure (to this file) used to track state machine context. - * The structure is not used directly, but instead to cast the "internal" - * member of the smf_ctx structure. - */ -struct internal_ctx { - bool new_state: 1; - bool terminate: 1; - bool is_exit: 1; - bool handled: 1; -}; - -#ifdef CONFIG_SMF_ANCESTOR_SUPPORT -static bool share_parent(const struct smf_state *test_state, const struct smf_state *target_state) -{ - for (const struct smf_state *state = test_state; state != NULL; state = state->parent) { - if (target_state == state) { - return true; - } - } - - return false; -} - -static const struct smf_state *get_child_of(const struct smf_state *states, - const struct smf_state *parent) -{ - const struct smf_state *tmp = states; - - while (true) { - if (tmp->parent == parent) { - return tmp; - } - - if (tmp->parent == NULL) { - return NULL; - } - - tmp = tmp->parent; - } -} - -static const struct smf_state *get_last_of(const struct smf_state *states) -{ - return get_child_of(states, NULL); -} - -/** - * @brief Find the Least Common Ancestor (LCA) of two states - * - * @param source transition source - * @param dest transition destination - * @return LCA state, or NULL if states have no LCA. - */ -static const struct smf_state *get_lca_of(const struct smf_state *source, - const struct smf_state *dest) -{ - for (const struct smf_state *ancestor = source->parent; ancestor != NULL; - ancestor = ancestor->parent) { - if (ancestor == dest) { - return ancestor->parent; - } else if (share_parent(dest, ancestor)) { - return ancestor; - } - } - - return NULL; -} - -/** - * @brief Executes all entry actions from the direct child of topmost to the new state - * - * @param ctx State machine context - * @param new_state State we are transitioning to - * @param topmost State we are entering from. Its entry action is not executed - * @return true if the state machine should terminate, else false - */ -static bool smf_execute_all_entry_actions(struct smf_ctx *const ctx, - const struct smf_state *new_state, - const struct smf_state *topmost) -{ - struct internal_ctx *const internal = (void *)&ctx->internal; - - if (new_state == topmost) { - /* There are no child states, so do nothing */ - return false; - } - - for (const struct smf_state *to_execute = get_child_of(new_state, topmost); - to_execute != NULL && to_execute != new_state; - to_execute = get_child_of(new_state, to_execute)) { - /* Keep track of the executing entry action in case it calls - * smf_set_state() - */ - ctx->executing = to_execute; - /* Execute every entry action EXCEPT that of the topmost state */ - if (to_execute->entry) { - to_execute->entry(ctx); - - /* No need to continue if terminate was set */ - if (internal->terminate) { - return true; - } - } - } - - /* and execute the new state entry action */ - ctx->executing = new_state; - if (new_state->entry) { - new_state->entry(ctx); - - /* No need to continue if terminate was set */ - if (internal->terminate) { - return true; - } - } - - return false; -} - -/** - * @brief Execute all ancestor run actions - * - * @param ctx State machine context - * @param target The run actions of this target's ancestors are executed - * @return true if the state machine should terminate, else false - */ -static bool smf_execute_ancestor_run_actions(struct smf_ctx *ctx) -{ - struct internal_ctx *const internal = (void *)&ctx->internal; - /* Execute all run actions in reverse order */ - - /* Return if the current state terminated */ - if (internal->terminate) { - return true; - } - - /* The child state either transitioned or handled it. Either way, stop propagating. */ - if (internal->new_state || internal->handled) { - return false; - } - - /* Try to run parent run actions */ - for (const struct smf_state *tmp_state = ctx->current->parent; tmp_state != NULL; - tmp_state = tmp_state->parent) { - /* Keep track of where we are in case an ancestor calls smf_set_state() */ - ctx->executing = tmp_state; - /* Execute parent run action */ - if (tmp_state->run) { - enum smf_state_result rc = tmp_state->run(ctx); - - if (rc == SMF_EVENT_HANDLED) { - internal->handled = true; - } - /* No need to continue if terminate was set */ - if (internal->terminate) { - return true; - } - - /* This state dealt with it. Stop propagating. */ - if (internal->new_state || internal->handled) { - break; - } - } - } - - /* All done executing the run actions */ - - return false; -} - -/** - * @brief Executes all exit actions from ctx->current to the direct child of topmost - * - * @param ctx State machine context - * @param topmost State we are exiting to. Its exit action is not executed - * @return true if the state machine should terminate, else false - */ -static bool smf_execute_all_exit_actions(struct smf_ctx *const ctx, const struct smf_state *topmost) -{ - struct internal_ctx *const internal = (void *)&ctx->internal; - - for (const struct smf_state *to_execute = ctx->current; - to_execute != NULL && to_execute != topmost; to_execute = to_execute->parent) { - if (to_execute->exit) { - to_execute->exit(ctx); - - /* No need to continue if terminate was set in the exit action */ - if (internal->terminate) { - return true; - } - } - } - - return false; -} -#endif /* CONFIG_SMF_ANCESTOR_SUPPORT */ - -/** - * @brief Reset the internal state of the state machine back to default values. - * Should be called on entry to smf_set_initial() and smf_set_state(). - * - * @param ctx State machine context. - */ -static void smf_clear_internal_state(struct smf_ctx *ctx) -{ - struct internal_ctx *const internal = (void *)&ctx->internal; - - internal->is_exit = false; - internal->terminate = false; - internal->handled = false; - internal->new_state = false; -} - -void smf_set_initial(struct smf_ctx *ctx, const struct smf_state *init_state) -{ -#ifdef CONFIG_SMF_INITIAL_TRANSITION - /* - * The final target will be the deepest leaf state that - * the target contains. Set that as the real target. - */ - while (init_state->initial) { - init_state = init_state->initial; - } -#endif - - smf_clear_internal_state(ctx); - ctx->current = init_state; - ctx->previous = NULL; - ctx->terminate_val = 0; - -#ifdef CONFIG_SMF_ANCESTOR_SUPPORT - struct internal_ctx *const internal = (void *)&ctx->internal; - - ctx->executing = init_state; - const struct smf_state *topmost = get_last_of(init_state); - - /* Execute topmost state entry action, since smf_execute_all_entry_actions() - * doesn't - */ - if (topmost->entry) { - topmost->entry(ctx); - if (internal->terminate) { - /* No need to continue if terminate was set */ - return; - } - } - - if (smf_execute_all_entry_actions(ctx, init_state, topmost)) { - /* No need to continue if terminate was set */ - return; - } -#else - /* execute entry action if it exists */ - if (init_state->entry) { - init_state->entry(ctx); - } -#endif -} - -void smf_set_state(struct smf_ctx *const ctx, const struct smf_state *new_state) -{ - struct internal_ctx *const internal = (void *)&ctx->internal; - - if (new_state == NULL) { - printf("new_state cannot be NULL"); - return; - } - - /* - * It does not make sense to call smf_set_state in an exit phase of a state - * since we are already in a transition; we would always ignore the - * intended state to transition into. - */ - if (internal->is_exit) { - printf("Calling %s from exit action", __func__); - return; - } - -#ifdef CONFIG_SMF_ANCESTOR_SUPPORT - const struct smf_state *topmost; - - if (share_parent(ctx->executing, new_state)) { - /* new state is a parent of where we are now*/ - topmost = new_state; - } else if (share_parent(new_state, ctx->executing)) { - /* we are a parent of the new state */ - topmost = ctx->executing; - } else { - /* not directly related, find LCA */ - topmost = get_lca_of(ctx->executing, new_state); - } - - internal->is_exit = true; - internal->new_state = true; - - /* call all exit actions up to (but not including) the topmost */ - if (smf_execute_all_exit_actions(ctx, topmost)) { - /* No need to continue if terminate was set in the exit action */ - return; - } - - /* if self-transition, call the exit action */ - if ((ctx->executing == new_state) && (new_state->exit)) { - new_state->exit(ctx); - - /* No need to continue if terminate was set in the exit action */ - if (internal->terminate) { - return; - } - } - - internal->is_exit = false; - - /* if self transition, call the entry action */ - if ((ctx->executing == new_state) && (new_state->entry)) { - new_state->entry(ctx); - - /* No need to continue if terminate was set in the entry action */ - if (internal->terminate) { - return; - } - } -#ifdef CONFIG_SMF_INITIAL_TRANSITION - /* - * The final target will be the deepest leaf state that - * the target contains. Set that as the real target. - */ - while (new_state->initial) { - new_state = new_state->initial; - } -#endif - - /* update the state variables */ - ctx->previous = ctx->current; - ctx->current = new_state; - - /* call all entry actions (except those of topmost) */ - if (smf_execute_all_entry_actions(ctx, new_state, topmost)) { - /* No need to continue if terminate was set in the entry action */ - return; - } -#else - /* Flat state machines have a very simple transition: */ - if (ctx->current->exit) { - internal->is_exit = true; - ctx->current->exit(ctx); - /* No need to continue if terminate was set in the exit action */ - if (internal->terminate) { - return; - } - internal->is_exit = false; - } - /* update the state variables */ - ctx->previous = ctx->current; - ctx->current = new_state; - - if (ctx->current->entry) { - ctx->current->entry(ctx); - /* No need to continue if terminate was set in the entry action */ - if (internal->terminate) { - return; - } - } -#endif -} - -void smf_set_terminate(struct smf_ctx *ctx, int32_t val) -{ - struct internal_ctx *const internal = (void *)&ctx->internal; - - internal->terminate = true; - ctx->terminate_val = val; -} - -int32_t smf_run_state(struct smf_ctx *const ctx) -{ - struct internal_ctx *const internal = (void *)&ctx->internal; - - /* No need to continue if terminate was set */ - if (internal->terminate) { - return ctx->terminate_val; - } - - /* Executing a states run function could cause a transition, so clear the - * internal state to ensure that the transition is handled correctly. - */ - smf_clear_internal_state(ctx); - -#ifdef CONFIG_SMF_ANCESTOR_SUPPORT - ctx->executing = ctx->current; - if (ctx->current->run) { - enum smf_state_result rc = ctx->current->run(ctx); - - if (rc == SMF_EVENT_HANDLED) { - internal->handled = true; - } - } - - if (smf_execute_ancestor_run_actions(ctx)) { - return ctx->terminate_val; - } -#else - if (ctx->current->run) { - ctx->current->run(ctx); - } -#endif - return 0; -} diff --git a/src/ocre/utils/c-smf/smf/smf.h b/src/ocre/utils/c-smf/smf/smf.h deleted file mode 100644 index e1d7d1e9..00000000 --- a/src/ocre/utils/c-smf/smf/smf.h +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright 2021 The Chromium OS Authors - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * - * @brief State Machine Framework header file - */ - -#ifndef ZEPHYR_INCLUDE_SMF_H_ -#define ZEPHYR_INCLUDE_SMF_H_ - -#include - -#define CONFIG_SMF_ANCESTOR_SUPPORT -#define CONFIG_SMF_INITIAL_TRANSITION - -/** - * @brief State Machine Framework API - * @defgroup smf State Machine Framework API - * @version 0.2.0 - * @ingroup os_services - * @{ - */ - -/** - * @brief Macro to create a hierarchical state with initial transitions. - * - * @param _entry State entry function or NULL - * @param _run State run function or NULL - * @param _exit State exit function or NULL - * @param _parent State parent object or NULL - * @param _initial State initial transition object or NULL - */ -/* clang-format off */ -#define SMF_CREATE_STATE(_entry, _run, _exit, _parent, _initial) \ -{ \ - .entry = _entry, \ - .run = _run, \ - .exit = _exit, \ - .parent = _parent, \ - .initial = _initial \ -} -/* clang-format on */ - -/** - * @brief Macro to cast user defined object to state machine - * context. - * - * @param o A pointer to the user defined object - */ -#define SMF_CTX(o) ((struct smf_ctx *)o) - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief enum for the return value of a state_execution function - */ -enum smf_state_result { - SMF_EVENT_HANDLED, - SMF_EVENT_PROPAGATE, -}; - -/** - * @brief Function pointer that implements a entry and exit actions - * of a state - * - * @param obj pointer user defined object - */ -typedef void (*state_method)(void *obj); - -/** - * @brief Function pointer that implements a the run action of a state - * - * @param obj pointer user defined object - * @return If the event should be propagated to parent states or not - * (Ignored when CONFIG_SMF_ANCESTOR_SUPPORT not defined) - */ -typedef enum smf_state_result (*state_execution)(void *obj); - -/** General state that can be used in multiple state machines. */ -struct smf_state { - /** Optional method that will be run when this state is entered */ - const state_method entry; - - /** - * Optional method that will be run repeatedly during state machine - * loop. - */ - const state_execution run; - - /** Optional method that will be run when this state exists */ - const state_method exit; -#ifdef CONFIG_SMF_ANCESTOR_SUPPORT - /** - * Optional parent state that contains common entry/run/exit - * implementation among various child states. - * entry: Parent function executes BEFORE child function. - * run: Parent function executes AFTER child function. - * exit: Parent function executes AFTER child function. - * - * Note: When transitioning between two child states with a shared - * parent, that parent's exit and entry functions do not execute. - */ - const struct smf_state *parent; - -#ifdef CONFIG_SMF_INITIAL_TRANSITION - /** - * Optional initial transition state. NULL for leaf states. - */ - const struct smf_state *initial; -#endif /* CONFIG_SMF_INITIAL_TRANSITION */ -#endif /* CONFIG_SMF_ANCESTOR_SUPPORT */ -}; - -/** Defines the current context of the state machine. */ -struct smf_ctx { - /** Current state the state machine is executing. */ - const struct smf_state *current; - /** Previous state the state machine executed */ - const struct smf_state *previous; - -#ifdef CONFIG_SMF_ANCESTOR_SUPPORT - /** Currently executing state (which may be a parent) */ - const struct smf_state *executing; -#endif /* CONFIG_SMF_ANCESTOR_SUPPORT */ - /** - * This value is set by the set_terminate function and - * should terminate the state machine when its set to a - * value other than zero when it's returned by the - * run_state function. - */ - int32_t terminate_val; - /** - * The state machine casts this to a "struct internal_ctx" and it's - * used to track state machine context - */ - uint32_t internal; -}; - -/** - * @brief Initializes the state machine and sets its initial state. - * - * @param ctx State machine context - * @param init_state Initial state the state machine starts in. - */ -void smf_set_initial(struct smf_ctx *ctx, const struct smf_state *init_state); - -/** - * @brief Changes a state machines state. This handles exiting the previous - * state and entering the target state. For HSMs the entry and exit - * actions of the Least Common Ancestor will not be run. - * - * @param ctx State machine context - * @param new_state State to transition to (NULL is valid and exits all states) - */ -void smf_set_state(struct smf_ctx *ctx, const struct smf_state *new_state); - -/** - * @brief Terminate a state machine - * - * @param ctx State machine context - * @param val Non-Zero termination value that's returned by the smf_run_state - * function. - */ -void smf_set_terminate(struct smf_ctx *ctx, int32_t val); - -/** - * @brief Runs one iteration of a state machine (including any parent states) - * - * @param ctx State machine context - * @return A non-zero value should terminate the state machine. This - * non-zero value could represent a terminal state being reached - * or the detection of an error that should result in the - * termination of the state machine. - */ -int32_t smf_run_state(struct smf_ctx *ctx); - -#ifdef __cplusplus -} -#endif - -/** - * @} - */ - -#endif /* ZEPHYR_INCLUDE_SMF_H_ */ diff --git a/src/ocre/utils/c-smf/test/CMakeLists.txt b/src/ocre/utils/c-smf/test/CMakeLists.txt deleted file mode 100644 index 6c2278f0..00000000 --- a/src/ocre/utils/c-smf/test/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -add_executable(test - test.c -) - -target_compile_options(test PRIVATE - -fdiagnostics-color=always - -pedantic-errors - -Wall - -Wextra - -Wconversion - -Wsign-conversion - -Werror -) diff --git a/src/ocre/utils/c-smf/test/test.c b/src/ocre/utils/c-smf/test/test.c deleted file mode 100644 index ebf7ea64..00000000 --- a/src/ocre/utils/c-smf/test/test.c +++ /dev/null @@ -1,73 +0,0 @@ -#include -#include "../smf/smf.h" - -// Define state entry, exit, and run actions -void state1_entry(void *ctx) { - (void)ctx; /* -Wunused-parameter */ - printf("Entering State 1\n"); -} - -void state1_exit(void *ctx) { - (void)ctx; /* -Wunused-parameter */ - printf("Exiting State 1\n"); -} - -void state1_run(void *ctx) { - (void)ctx; /* -Wunused-parameter */ - printf("Running State 1\n"); -} - -void state2_entry(void *ctx) { - (void)ctx; /* -Wunused-parameter */ - printf("Entering State 2\n"); -} - -void state2_exit(void *ctx) { - (void)ctx; /* -Wunused-parameter */ - printf("Exiting State 2\n"); -} - -void state2_run(void *ctx) { - (void)ctx; /* -Wunused-parameter */ - printf("Running State 2\n"); -} - -// Define states -struct smf_state state1 = { - .entry = state1_entry, - .run = state1_run, - .exit = state1_exit, -#ifdef CONFIG_SMF_ANCESTOR_SUPPORT - .parent = NULL, -#endif /* CONFIG_SMF_ANCESTOR_SUPPORT */ -}; - -struct smf_state state2 = { - .entry = state2_entry, - .run = state2_run, - .exit = state2_exit, -#ifdef CONFIG_SMF_ANCESTOR_SUPPORT - .parent = NULL, -#endif /* CONFIG_SMF_ANCESTOR_SUPPORT */ -}; - -int main() { - struct smf_ctx ctx; - - // Initialize the state machine with the initial state - smf_set_initial(&ctx, &state1); - - // Run the initial state - printf("Starting State Machine\n"); - smf_run_state(&ctx); - - // Transition to a new state - printf("Transitioning to State 2\n"); - smf_set_state(&ctx, &state2); - - // Run the new state - smf_run_state(&ctx); - - printf("State Machine Test Complete\n"); - return 0; -} \ No newline at end of file diff --git a/src/ocre/version.h b/src/ocre/version.h new file mode 100644 index 00000000..09772e27 --- /dev/null +++ b/src/ocre/version.h @@ -0,0 +1 @@ +#define OCRE_VERSION_STRING "0.7.0" diff --git a/src/platform/include/ocre/platform/file.h b/src/platform/include/ocre/platform/file.h new file mode 100644 index 00000000..42f250d7 --- /dev/null +++ b/src/platform/include/ocre/platform/file.h @@ -0,0 +1,4 @@ +#include + +void *ocre_load_file(const char *path, size_t *size); +int ocre_unload_file(void *buffer, size_t size); diff --git a/src/platform/include/ocre/platform/memory.h b/src/platform/include/ocre/platform/memory.h new file mode 100644 index 00000000..b649d0a1 --- /dev/null +++ b/src/platform/include/ocre/platform/memory.h @@ -0,0 +1,6 @@ +#include + +void *user_malloc(size_t size); +void user_free(void *p); +void *user_calloc(size_t n, size_t size); +void *user_realloc(void *p, size_t size); diff --git a/src/platform/posix/CMakeLists.txt b/src/platform/posix/CMakeLists.txt new file mode 100644 index 00000000..50bede67 --- /dev/null +++ b/src/platform/posix/CMakeLists.txt @@ -0,0 +1,14 @@ +add_library(OcrePlatform) + +target_sources(OcrePlatform + PRIVATE + memory.c + file_mmap.c + # file_alloc_read.c +) + +target_include_directories(OcrePlatform + PUBLIC + include + ../include +) diff --git a/src/platform/posix/file_alloc_fread.c b/src/platform/posix/file_alloc_fread.c new file mode 100644 index 00000000..30c4e631 --- /dev/null +++ b/src/platform/posix/file_alloc_fread.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +LOG_MODULE_REGISTER(file_alloc_fread); + +void *ocre_load_file(const char *path, size_t *size) +{ + if (!path) { + LOG_ERR("Invalid arguments"); + goto error; + } + + FILE *fp = fopen(path, "rb"); + if (!fp) { + LOG_ERR("Failed to open file '%s' errno=%d", path, errno); + goto error; + } + + int fd = fileno(fp); + if (fd < 0) { + LOG_ERR("Failed to get file descriptor errno=%d", errno); + goto close_file; + } + + struct stat finfo; + + int rc; + rc = fstat(fd, &finfo); + if (rc < 0) { + LOG_ERR("Failed to get file info: rc=%d errno=%d", rc, errno); + goto close_file; + } + + size_t file_size = (size_t)finfo.st_size; + // + // size_t file_size = 100; + // + + LOG_INF("File size to load: %zu", file_size); + + if (!file_size) { + LOG_ERR("File is empty"); + goto close_file; + } + + void *buffer = user_malloc(file_size); + if (!buffer) { + LOG_ERR("Failed to allocate memory for file buffer size=%zu errno=%d", file_size, errno); + goto close_file; + } + + memset(buffer, 0, file_size); + + // fseek(fp, 0, SEEK_SET); + + // read from file into buffer + size_t bytes_read = fread(buffer, 1, file_size, fp); + + if (bytes_read != file_size) { + LOG_ERR("Failed to read file bytes_read=%zu errno=%d", bytes_read, errno); + goto free_buffer; + } + + rc = fclose(fp); + if (rc) { + LOG_ERR("Failed to close file rc=%d errno=%d", rc, errno); + } + + *size = file_size; + + LOG_INF("File '%s' (size=%zu) loaded successfully", path, file_size); + + return buffer; + +free_buffer: + user_free(buffer); + +close_file: + rc = fclose(fp); + if (rc) { + LOG_ERR("Failed to close file: rc=%d errno=%d", rc, errno); + } + +error: + return NULL; +} + +int ocre_unload_file(void *buffer, size_t size) +{ + user_free(buffer); + + return 0; +} diff --git a/src/platform/posix/file_alloc_read.c b/src/platform/posix/file_alloc_read.c new file mode 100644 index 00000000..df07e44a --- /dev/null +++ b/src/platform/posix/file_alloc_read.c @@ -0,0 +1,95 @@ +#include +#include +#include +// #include +#include +#include + +#include +#include + +#include +#include + +LOG_MODULE_REGISTER(file_alloc_read); + +void *ocre_load_file(const char *path, size_t *size) +{ + if (!path) { + LOG_ERR("Invalid arguments"); + goto error; + } + + int fd = open(path, O_RDONLY); + if (fd < 0) { + LOG_ERR("Failed to open file '%s' errno=%d", path, errno); + goto error; + } + + struct stat finfo; + int rc = fstat(fd, &finfo); + if (rc < 0) { + LOG_ERR("Failed to get file info rc=%d errno=%d", rc, errno); + goto close_file; + } + + ssize_t file_size = (ssize_t)finfo.st_size; + // + // size_t file_size = 100; + // + + LOG_INF("File size to load: %zu", file_size); + + if (!file_size) { + LOG_ERR("File is empty"); + goto close_file; + } + + void *buffer = user_malloc(file_size); + if (!buffer) { + LOG_ERR("Failed to allocate memory for file buffer size=%zu errno=%d", file_size, errno); + goto close_file; + } + + memset(buffer, 0, file_size); + + // fseek(fp, 0, SEEK_SET); + + // read from file into buffer + ssize_t bytes_read = read(fd, buffer, file_size); + + if (bytes_read != file_size) { + LOG_ERR("Failed to read file bytes_read=%zu errno=%d", bytes_read, errno); + goto free_buffer; + } + + rc = close(fd); + if (rc) { + LOG_ERR("Failed to close file rc=%d errno=%d", rc, errno); + } + + *size = file_size; + + LOG_INF("File '%s' (size=%zu) loaded successfully", path, file_size); + + return buffer; + +free_buffer: + user_free(buffer); + +close_file: + rc = close(fd); + if (rc) { + LOG_ERR("Failed to close file: rc=%d errno=%d", rc, errno); + } + +error: + return NULL; +} + +int ocre_unload_file(void *buffer, size_t size) +{ + user_free(buffer); + + return 0; +} diff --git a/src/platform/posix/file_mmap.c b/src/platform/posix/file_mmap.c new file mode 100644 index 00000000..98bbe1c8 --- /dev/null +++ b/src/platform/posix/file_mmap.c @@ -0,0 +1,89 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +LOG_MODULE_REGISTER(file_mmap); + +void *ocre_load_file(const char *path, size_t *size) +{ + int save_errno = 0; + void *buffer = NULL; + + if (!path) { + LOG_ERR("Invalid arguments"); + save_errno = EINVAL; + goto error_errno; + } + + FILE *fp = fopen(path, "rb"); + if (!fp) { + save_errno = errno; + LOG_ERR("Failed to open file '%s': errno=%d", path, save_errno); + goto error_errno; + } + + int fd = fileno(fp); + if (fd < 0) { + save_errno = errno; + LOG_ERR("Failed to get file descriptor (fd=%d): errno=%d", fd, save_errno); + goto error_close; + } + + struct stat finfo; + int rc = fstat(fd, &finfo); + if (rc < 0) { + save_errno = errno; + LOG_ERR("Failed to get file info: rc=%d errno=%d", rc, save_errno); + goto error_close; + } + + size_t file_size = finfo.st_size; + if (!file_size) { + LOG_WRN("File is empty"); + } + + buffer = mmap(NULL, file_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + if (!buffer || buffer == MAP_FAILED) { + save_errno = errno; + LOG_ERR("Failed to mmap file %zu errno=%d", file_size, errno); + goto error_close; + } + + if (fclose(fp) != 0) { + LOG_ERR("Failed to close file errno=%d", errno); + } + + *size = file_size; + + LOG_INF("File '%s' (size=%zu) mmapped successfully", path, file_size); + + return buffer; + +error_close: + fclose(fp); + +error_errno: + errno = save_errno; + + return NULL; +} + +int ocre_unload_file(void *buffer, size_t size) +{ + if (munmap(buffer, size)) { + int save_errno = errno; + LOG_ERR("Failed to munmap file errno=%d", save_errno); + errno = save_errno; + return -1; + } + + return 0; +} diff --git a/src/platform/posix/include/ocre/platform/config.h b/src/platform/posix/include/ocre/platform/config.h new file mode 100644 index 00000000..b00b72b6 --- /dev/null +++ b/src/platform/posix/include/ocre/platform/config.h @@ -0,0 +1,23 @@ +#ifndef OCRE_PLATFORM_POSIX_H +#define OCRE_PLATFORM_POSIX_H + +#define CONFIG_OCRE_DEFAULT_WORKING_DIRECTORY "./var/lib/ocre" + +#define CONFIG_OCRE_WAMR_INTERPRETER 1 +#define CONFIG_OCRE_WAMR_AOT 1 +#define CONFIG_OCRE_WAMR_HEAP_BUFFER_SIZE 32768 +#define CONFIG_OCRE_CONTAINER_DEFAULT_HEAP_SIZE 4096 +#define CONFIG_OCRE_CONTAINER_DEFAULT_STACK_SIZE 2048 +#define CONFIG_OCRE_TIMER 1 +#define CONFIG_OCRE_MAX_TIMERS 5 +#define CONFIG_OCRE_LOG_LEVEL_DEFAULT 1 +#define CONFIG_OCRE_LOG_LEVEL 3 +#define CONFIG_OCRE_NETWORKING 1 +#define CONFIG_OCRE_FILESYSTEM 1 +#define CONFIG_OCRE_CONTAINER_MESSAGING 1 +#define CONFIG_OCRE_MESSAGING_MAX_SUBSCRIPTIONS 32 +#define CONFIG_OCRE_SHARED_HEAP 1 +#define CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL 1 +#define OCRE_SHARED_HEAP_BUF_SIZE 131072 + +#endif /* OCRE_PLATFORM_POSIX_H */ diff --git a/src/platform/posix/include/ocre/platform/log.h b/src/platform/posix/include/ocre/platform/log.h new file mode 100644 index 00000000..7b0d03f2 --- /dev/null +++ b/src/platform/posix/include/ocre/platform/log.h @@ -0,0 +1,8 @@ +#include + +#define LOG_MODULE_REGISTER(module, ...) static const char *const __ocre_log_module = #module + +#define LOG_ERR(fmt, ...) fprintf(stderr, " %s: " fmt "\n", __ocre_log_module, ##__VA_ARGS__); +#define LOG_WRN(fmt, ...) fprintf(stderr, " %s: " fmt "\n", __ocre_log_module, ##__VA_ARGS__); +#define LOG_INF(fmt, ...) fprintf(stderr, " %s: " fmt "\n", __ocre_log_module, ##__VA_ARGS__); +#define LOG_DBG(fmt, ...) fprintf(stderr, " %s: " fmt "\n", __ocre_log_module, ##__VA_ARGS__); diff --git a/src/platform/posix/memory.c b/src/platform/posix/memory.c new file mode 100644 index 00000000..d3be68a5 --- /dev/null +++ b/src/platform/posix/memory.c @@ -0,0 +1,22 @@ +#include +#include + +void *user_malloc(size_t size) +{ + return malloc(size); +} + +void user_free(void *p) +{ + free(p); +} + +void *user_calloc(size_t n, size_t size) +{ + return calloc(n, size); +} + +void *user_realloc(void *p, size_t size) +{ + return realloc(p, size); +} diff --git a/src/platform/zephyr/CMakeLists.txt b/src/platform/zephyr/CMakeLists.txt new file mode 100644 index 00000000..1ebf1ac0 --- /dev/null +++ b/src/platform/zephyr/CMakeLists.txt @@ -0,0 +1,18 @@ +add_library(OcrePlatform) + +target_sources(OcrePlatform + PRIVATE + memory.c + ../posix/file_alloc_read.c +) + +target_include_directories(OcrePlatform + PUBLIC + include + ../include +) + +target_link_libraries(OcrePlatform + PUBLIC + zephyr_interface +) diff --git a/src/platform/zephyr/include/ocre/platform/config.h b/src/platform/zephyr/include/ocre/platform/config.h new file mode 100644 index 00000000..7c18adf5 --- /dev/null +++ b/src/platform/zephyr/include/ocre/platform/config.h @@ -0,0 +1 @@ +/* Zephyr includes autoconf.h automatically */ diff --git a/src/platform/zephyr/include/ocre/platform/log.h b/src/platform/zephyr/include/ocre/platform/log.h new file mode 100644 index 00000000..3cd34de3 --- /dev/null +++ b/src/platform/zephyr/include/ocre/platform/log.h @@ -0,0 +1 @@ +#include diff --git a/src/platform/zephyr/memory.c b/src/platform/zephyr/memory.c new file mode 100644 index 00000000..d98b89ef --- /dev/null +++ b/src/platform/zephyr/memory.c @@ -0,0 +1,49 @@ +/** + * @copyright Copyright © contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include + +#ifdef CONFIG_SHARED_MULTI_HEAP +void *user_malloc(size_t size) +{ + return shared_multi_heap_aligned_alloc(SMH_REG_ATTR_EXTERNAL, 32, size); +} + +void user_free(void *ptr) +{ + shared_multi_heap_free(ptr); +} + +void *user_realloc(void *ptr, size_t size) +{ + // TODO + return NULL; +} + +#else + +#warning CONFIG_SHARED_MULTI_HEAP is not defined. Using internal RAM + +void *user_malloc(size_t size) +{ + return malloc(size); +} + +void user_free(void *ptr) +{ + free(ptr); +} + +void *user_realloc(void *ptr, size_t size) +{ + return realloc(ptr, size); +} + +#endif diff --git a/src/runtime/CMakeLists.txt b/src/runtime/CMakeLists.txt new file mode 100644 index 00000000..d5d0dc57 --- /dev/null +++ b/src/runtime/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.20) + +add_library(OcreRuntime + INTERFACE + include/ocre/runtime/vtable.h +) + +target_include_directories(OcreRuntime + INTERFACE + include +) diff --git a/src/runtime/include/ocre/runtime/vtable.h b/src/runtime/include/ocre/runtime/vtable.h new file mode 100644 index 00000000..b7bffbf1 --- /dev/null +++ b/src/runtime/include/ocre/runtime/vtable.h @@ -0,0 +1,20 @@ +#ifndef OCRE_RUNTIME_VTABLE_H +#define OCRE_RUNTIME_VTABLE_H + +#include + +struct ocre_runtime_vtable { + const char *const runtime_name; + int (*init)(void); + int (*deinit)(void); + + void *(*create)(const char *path, size_t stack_size, size_t heap_size, const char **capabilities, + const char **argv, const char **envp, const char **mounts); + int (*destroy)(void *runtime_context); + int (*thread_execute)(void *arg); + int (*kill)(void *runtime_context); + int (*pause)(void *runtime_context); + int (*unpause)(void *runtime_context); +}; + +#endif /* OCRE_RUNTIME_VTABLE_H */ diff --git a/src/runtime/wamr/CMakeLists.txt b/src/runtime/wamr/CMakeLists.txt new file mode 100644 index 00000000..6e54b27e --- /dev/null +++ b/src/runtime/wamr/CMakeLists.txt @@ -0,0 +1,21 @@ +add_library(OcreRuntimeWamr) + +target_sources(OcreRuntimeWamr + PRIVATE + wamr.c +) + +target_include_directories(OcreRuntimeWamr + PUBLIC + include +) + +target_link_libraries(OcreRuntimeWamr + PUBLIC + OcreRuntime + OcrePlatform + OcreRuntimeAPI + vmlib +) + +add_subdirectory(ocre_api) diff --git a/src/runtime/wamr/include/ocre/runtime/wamr/wamr.h b/src/runtime/wamr/include/ocre/runtime/wamr/wamr.h new file mode 100644 index 00000000..b35e45b9 --- /dev/null +++ b/src/runtime/wamr/include/ocre/runtime/wamr/wamr.h @@ -0,0 +1,8 @@ +#ifndef OCRE_RUNTIME_WAMR_H +#define OCRE_RUNTIME_WAMR_H + +#include + +extern const struct ocre_runtime_vtable wamr_vtable; + +#endif /* OCRE_RUNTIME_WAMR_H */ diff --git a/src/runtime/wamr/ocre_api/CMakeLists.txt b/src/runtime/wamr/ocre_api/CMakeLists.txt new file mode 100644 index 00000000..d3b00299 --- /dev/null +++ b/src/runtime/wamr/ocre_api/CMakeLists.txt @@ -0,0 +1,29 @@ +add_library(OcreRuntimeAPI) + +target_sources(OcreRuntimeAPI + PRIVATE + ocre_api.c + ocre_common.c + ocre_timers/ocre_timer.c + ocre_messaging/ocre_messaging.c + utils/strlcat.c + core/core_eventq.c + core/core_misc.c + core/core_timer.c + core/core_mutex.c + core/core_slist.c + core/core_memory.c + +) + +# target_include_directories(OcreRuntimeAPI +# PUBLIC +# include +# ) + +target_link_libraries(OcreRuntimeAPI + PUBLIC + # OcreRuntime + OcrePlatform + vmlib +) diff --git a/src/runtime/wamr/ocre_api/core/core_eventq.c b/src/runtime/wamr/ocre_api/core/core_eventq.c new file mode 100644 index 00000000..9ecbfe51 --- /dev/null +++ b/src/runtime/wamr/ocre_api/core/core_eventq.c @@ -0,0 +1,79 @@ +/** + * @copyright Copyright © contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "core_external.h" + +int core_eventq_init(core_eventq_t *eventq, size_t item_size, size_t max_items) +{ + eventq->buffer = core_malloc(item_size * max_items); + if (!eventq->buffer) { + return -ENOMEM; + } + eventq->item_size = item_size; + eventq->max_items = max_items; + eventq->count = 0; + eventq->head = 0; + eventq->tail = 0; + pthread_mutex_init(&eventq->mutex, NULL); + pthread_cond_init(&eventq->cond, NULL); + return 0; +} + +int core_eventq_peek(core_eventq_t *eventq, void *event) +{ + pthread_mutex_lock(&eventq->mutex); + if (eventq->count == 0) { + pthread_mutex_unlock(&eventq->mutex); + return -ENOMSG; + } + memcpy(event, (char *)eventq->buffer + (eventq->head * eventq->item_size), eventq->item_size); + pthread_mutex_unlock(&eventq->mutex); + return 0; +} + +int core_eventq_get(core_eventq_t *eventq, void *event) +{ + pthread_mutex_lock(&eventq->mutex); + if (eventq->count == 0) { + pthread_mutex_unlock(&eventq->mutex); + return -ENOENT; + } + memcpy(event, (char *)eventq->buffer + (eventq->head * eventq->item_size), eventq->item_size); + eventq->head = (eventq->head + 1) % eventq->max_items; + eventq->count--; + pthread_mutex_unlock(&eventq->mutex); + return 0; +} + +int core_eventq_put(core_eventq_t *eventq, const void *event) +{ + pthread_mutex_lock(&eventq->mutex); + if (eventq->count >= eventq->max_items) { + pthread_mutex_unlock(&eventq->mutex); + return -ENOMEM; + } + memcpy((char *)eventq->buffer + (eventq->tail * eventq->item_size), event, eventq->item_size); + eventq->tail = (eventq->tail + 1) % eventq->max_items; + eventq->count++; + pthread_cond_signal(&eventq->cond); + pthread_mutex_unlock(&eventq->mutex); + return 0; +} + +void core_eventq_destroy(core_eventq_t *eventq) +{ + pthread_mutex_destroy(&eventq->mutex); + pthread_cond_destroy(&eventq->cond); + if (eventq->buffer) { + core_free(eventq->buffer); + eventq->buffer = NULL; + } +} diff --git a/src/shared/platform/ocre_core_external.h b/src/runtime/wamr/ocre_api/core/core_external.h similarity index 90% rename from src/shared/platform/ocre_core_external.h rename to src/runtime/wamr/ocre_api/core/core_external.h index 79efb20f..c99876f3 100644 --- a/src/shared/platform/ocre_core_external.h +++ b/src/runtime/wamr/ocre_api/core/core_external.h @@ -12,11 +12,7 @@ #include #include -#ifdef __ZEPHYR__ -#include "zephyr/core_internal.h" -#else -#include "posix/core_internal.h" -#endif +#include "core_internal.h" #define OCRE_MODULE_NAME_LEN 16 @@ -45,7 +41,8 @@ typedef struct core_thread core_thread_t; * @param priority Thread priority. * @return 0 on success, negative value on error. */ -int core_thread_create(core_thread_t *thread, core_thread_func_t func, void *arg, const char *name, size_t stack_size, int priority); +int core_thread_create(core_thread_t *thread, core_thread_func_t func, void *arg, const char *name, size_t stack_size, + int priority); /** * @brief Destroy a thread and release its resources. @@ -142,30 +139,6 @@ void *core_malloc(size_t size); */ void core_free(void *ptr); -/** - * @brief Allocate memory in application heap. - * - * @param size Number of bytes to allocate. - * @return Pointer to allocated memory, or NULL on failure. - */ -void *user_malloc(size_t size); - -/** - * @brief Free previously allocated memory in application heap. - * - * @param ptr Pointer to memory to free. - */ -void user_free(void *ptr); - -/** - * @brief Reallocate memory in application heap. - * - * @param ptr pointer to already allocated memory - * @param size Number of bytes to allocate. - * @return Pointer to reallocated memory, or NULL on failure. - */ -void *user_realloc(void *ptr, size_t size); - /** * @brief Yield the current thread's execution. */ diff --git a/src/runtime/wamr/ocre_api/core/core_internal.h b/src/runtime/wamr/ocre_api/core/core_internal.h new file mode 100644 index 00000000..114481ba --- /dev/null +++ b/src/runtime/wamr/ocre_api/core/core_internal.h @@ -0,0 +1,167 @@ +/** + * @copyright Copyright © contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef OCRE_CORE_INTERNAL_H +#define OCRE_CORE_INTERNAL_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// Constants + +/** + * @brief Sets the value of argc for internal use. + * + * This function stores the argc value passed from main + * so that other functions in the module can access it + * without relying on global variables. + * + * @param argc The argument count from main. + */ +void set_argc(int argc); + +/** + * @brief Application version string. + */ +#ifndef APP_VERSION_STRING +#define APP_VERSION_STRING "0.0.0-dev" +#endif /* APP_VERSION_STRING */ + +/** + * @brief Structure representing a thread in the Ocre runtime. + */ +struct core_thread { + pthread_t tid; /*!< POSIX thread identifier */ + void *stack; /*!< Pointer to thread stack memory */ + size_t stack_size; /*!< Size of the thread stack */ + uint32_t user_options; /*!< User-defined options for the thread */ +}; + +/** + * @brief Structure representing a mutex in the Ocre runtime. + */ +struct core_mutex { + pthread_mutex_t native_mutex; /*!< POSIX mutex */ +}; + +/** + * @brief Structure representing a message queue in the Ocre runtime. + */ +struct core_mq { + mqd_t msgq; /*!< POSIX message queue descriptor */ +}; + +/** + * @brief Timer callback function type. + * + * @param user_data Pointer to user data passed to the callback. + */ +typedef void (*core_timer_callback_t)(void *user_data); + +/** + * @brief Structure representing a timer in the Ocre runtime. + */ +struct core_timer { + timer_t timerid; /*!< POSIX timer identifier */ + core_timer_callback_t cb; /*!< Timer callback function */ + void *user_data; /*!< User data for the callback */ +}; + +/* Generic singly-linked list iteration macros */ +#define CORE_SLIST_CONTAINER_OF(ptr, type, member) ((type *)((char *)(ptr) - offsetof(type, member))) + +#define CORE_SLIST_FOR_EACH_CONTAINER_SAFE(list, var, tmp, member) \ + for (var = (list)->head ? CORE_SLIST_CONTAINER_OF((list)->head, __typeof__(*var), member) : NULL, \ + tmp = var ? (var->member.next ? CORE_SLIST_CONTAINER_OF(var->member.next, __typeof__(*var), member) \ + : NULL) \ + : NULL; \ + var; var = tmp, \ + tmp = tmp ? (tmp->member.next ? CORE_SLIST_CONTAINER_OF(tmp->member.next, __typeof__(*var), member) \ + : NULL) \ + : NULL) + +#define CORE_SLIST_FOR_EACH_CONTAINER(list, var, member) \ + for (var = (list)->head ? CORE_SLIST_CONTAINER_OF((list)->head, __typeof__(*var), member) : NULL; var; \ + var = var->member.next ? CORE_SLIST_CONTAINER_OF(var->member.next, __typeof__(*var), member) : NULL) + +/** + * @brief Structure representing a node in a singly-linked list. + */ +typedef struct core_snode { + struct core_snode *next; /*!< Pointer to the next node in the list */ +} core_snode_t; + +/** + * @brief Structure representing a singly-linked list for POSIX platform. + */ +typedef struct { + core_snode_t *head; /*!< Pointer to the first node in the list */ + core_snode_t *tail; /*!< Pointer to the last node in the list */ +} core_slist_t; + +/** + * @brief Initialize a singly-linked list. + * + * @param list Pointer to the list to initialize. + */ +void core_slist_init(core_slist_t *list); + +/** + * @brief Append a node to the end of a singly-linked list. + * + * @param list Pointer to the list to append to. + * @param node Pointer to the node to append. + */ +void core_slist_append(core_slist_t *list, core_snode_t *node); + +/** + * @brief Remove a node from a singly-linked list. + * + * @param list Pointer to the list to remove from. + * @param prev Pointer to the previous node (or NULL if removing head). + * @param node Pointer to the node to remove. + */ +void core_slist_remove(core_slist_t *list, core_snode_t *prev, core_snode_t *node); + +/** + * @brief Spinlock type for POSIX platform (simulated using mutex). + */ +typedef struct { + pthread_mutex_t mutex; /*!< POSIX mutex for spinlock simulation */ +} core_spinlock_t; + +/** + * @brief Spinlock key type for POSIX platform. + */ +typedef int core_spinlock_key_t; + +/** + * @brief Generic event queue structure for POSIX platform. + * + * A thread-safe circular buffer implementation that can store + * any type of data items with configurable size and capacity. + */ +typedef struct { + void *buffer; /*!< Dynamically allocated buffer for queue items */ + size_t item_size; /*!< Size of each individual item in bytes */ + size_t max_items; /*!< Maximum number of items the queue can hold */ + size_t count; /*!< Current number of items in the queue */ + size_t head; /*!< Index of the next item to be read */ + size_t tail; /*!< Index where the next item will be written */ + pthread_mutex_t mutex; /*!< Mutex for thread-safe access */ + pthread_cond_t cond; /*!< Condition variable for signaling */ +} core_eventq_t; + +#endif /* OCRE_CORE_INTERNAL_H */ diff --git a/src/messaging/message_types.h b/src/runtime/wamr/ocre_api/core/core_memory.c similarity index 55% rename from src/messaging/message_types.h rename to src/runtime/wamr/ocre_api/core/core_memory.c index 4e3bb55f..cfd3471b 100644 --- a/src/messaging/message_types.h +++ b/src/runtime/wamr/ocre_api/core/core_memory.c @@ -1,13 +1,20 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef OCRE_MESSAGING_TYPES_H -#define OCRE_MESSAGING_TYPES_H - -struct base {}; - -#endif \ No newline at end of file +/** + * @copyright Copyright © contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "core_external.h" + +void *core_malloc(size_t size) +{ + return malloc(size); +} + +void core_free(void *ptr) +{ + free(ptr); +} diff --git a/src/runtime/wamr/ocre_api/core/core_misc.c b/src/runtime/wamr/ocre_api/core/core_misc.c new file mode 100644 index 00000000..cf85a8ed --- /dev/null +++ b/src/runtime/wamr/ocre_api/core/core_misc.c @@ -0,0 +1,60 @@ +/** + * @copyright Copyright © contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "core_external.h" + +#include +#include +#include +#include +#include + +void core_sleep_ms(int milliseconds) +{ + struct timespec ts; + int res; + + if (milliseconds < 0) { + errno = EINVAL; + fprintf(stderr, "core_sleep_ms: Invalid milliseconds value (%d)\n", milliseconds); + return; + } + + ts.tv_sec = milliseconds / 1000; + ts.tv_nsec = (milliseconds % 1000) * 1000000; + + do { + res = nanosleep(&ts, &ts); + if (res && errno != EINTR) { + fprintf(stderr, "core_sleep_ms: nanosleep failed (errno=%d)\n", errno); + } + } while (res && errno == EINTR); +} + +void core_yield(void) +{ + sched_yield(); +} + +uint32_t core_uptime_get(void) +{ + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return (uint32_t)(ts.tv_sec * 1000 + ts.tv_nsec / 1000000); +} + +core_spinlock_key_t core_spinlock_lock(core_spinlock_t *lock) +{ + pthread_mutex_lock(&lock->mutex); + return 0; +} + +void core_spinlock_unlock(core_spinlock_t *lock, core_spinlock_key_t key) +{ + (void)key; + pthread_mutex_unlock(&lock->mutex); +} diff --git a/src/runtime/wamr/ocre_api/core/core_mutex.c b/src/runtime/wamr/ocre_api/core/core_mutex.c new file mode 100644 index 00000000..5c511458 --- /dev/null +++ b/src/runtime/wamr/ocre_api/core/core_mutex.c @@ -0,0 +1,33 @@ +/** + * @copyright Copyright © contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "core_external.h" + +#include +#include + +int core_mutex_init(core_mutex_t *mutex) +{ + if (!mutex) + return -1; + return pthread_mutex_init(&mutex->native_mutex, NULL); +} + +int core_mutex_destroy(core_mutex_t *mutex) +{ + return pthread_mutex_destroy(&mutex->native_mutex); +} + +int core_mutex_lock(core_mutex_t *mutex) +{ + return pthread_mutex_lock(&mutex->native_mutex); +} + +int core_mutex_unlock(core_mutex_t *mutex) +{ + return pthread_mutex_unlock(&mutex->native_mutex); +} diff --git a/src/runtime/wamr/ocre_api/core/core_slist.c b/src/runtime/wamr/ocre_api/core/core_slist.c new file mode 100644 index 00000000..2f87fe1d --- /dev/null +++ b/src/runtime/wamr/ocre_api/core/core_slist.c @@ -0,0 +1,38 @@ +/** + * @copyright Copyright © contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "core_external.h" + +void core_slist_init(core_slist_t *list) +{ + list->head = NULL; + list->tail = NULL; +} + +void core_slist_append(core_slist_t *list, core_snode_t *node) +{ + node->next = NULL; + if (list->tail) { + list->tail->next = node; + } else { + list->head = node; + } + list->tail = node; +} + +void core_slist_remove(core_slist_t *list, core_snode_t *prev, core_snode_t *node) +{ + if (prev) { + prev->next = node->next; + } else { + list->head = node->next; + } + if (list->tail == node) { + list->tail = prev; + } +} diff --git a/src/runtime/wamr/ocre_api/core/core_timer.c b/src/runtime/wamr/ocre_api/core/core_timer.c new file mode 100644 index 00000000..a758e70a --- /dev/null +++ b/src/runtime/wamr/ocre_api/core/core_timer.c @@ -0,0 +1,59 @@ +/** + * @copyright Copyright © contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include "core_external.h" + +static void posix_timer_cb(union sigval sv) +{ + core_timer_t *timer = (core_timer_t *)sv.sival_ptr; + if (timer->cb) { + timer->cb(timer->user_data); + } +} + +int core_timer_init(core_timer_t *timer, core_timer_callback_t cb, void *user_data) +{ + if (!timer) + return -1; + struct sigevent sev = {0}; + timer->cb = cb; + timer->user_data = user_data; + sev.sigev_notify = SIGEV_THREAD; + sev.sigev_notify_function = posix_timer_cb; + sev.sigev_value.sival_ptr = timer; + return timer_create(CLOCK_REALTIME, &sev, &timer->timerid); +} + +int core_timer_start(core_timer_t *timer, int timeout_ms, int period_ms) +{ + if (!timer) + return -1; + struct itimerspec its; + if (timeout_ms == 0 && period_ms > 0) { + its.it_value.tv_sec = period_ms / 1000; + its.it_value.tv_nsec = (period_ms % 1000) * 1000000; + } else { + its.it_value.tv_sec = timeout_ms / 1000; + its.it_value.tv_nsec = (timeout_ms % 1000) * 1000000; + } + its.it_interval.tv_sec = period_ms / 1000; + its.it_interval.tv_nsec = (period_ms % 1000) * 1000000; + return timer_settime(timer->timerid, 0, &its, NULL); +} + +int core_timer_stop(core_timer_t *timer) +{ + if (!timer) + return -1; + struct itimerspec its = {0}; + return timer_settime(timer->timerid, 0, &its, NULL); +} diff --git a/src/runtime/wamr/ocre_api/ocre_api.c b/src/runtime/wamr/ocre_api/ocre_api.c new file mode 100644 index 00000000..1ca8db8c --- /dev/null +++ b/src/runtime/wamr/ocre_api/ocre_api.c @@ -0,0 +1,158 @@ +/** + * @copyright Copyright © contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include + +#include "ocre_api.h" +#include "utils/strlcat.h" + +#include + +#ifdef CONFIG_OCRE_TIMER +#include "ocre_timers/ocre_timer.h" +#endif + +#if defined(CONFIG_OCRE_TIMER) || defined(CONFIG_OCRE_GPIO) || defined(CONFIG_OCRE_SENSORS) || \ + defined(CONFIG_OCRE_CONTAINER_MESSAGING) +#include "ocre_common.h" +#endif + +#ifdef CONFIG_OCRE_SENSORS +#include "ocre_sensors/ocre_sensors.h" +#endif + +#ifdef CONFIG_OCRE_GPIO +#include "ocre_gpio/ocre_gpio.h" +#endif + +#ifdef CONFIG_OCRE_CONTAINER_MESSAGING +#include "ocre_messaging/ocre_messaging.h" +#endif + +#ifndef APP_VERSION_STRING +#define APP_VERSION_STRING "1.0.0" +#endif + +int _ocre_posix_uname(wasm_exec_env_t exec_env, struct _ocre_posix_utsname *name) +{ + wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); + if (!module_inst) { + return -1; + } + if (!wasm_runtime_validate_native_addr(module_inst, name, sizeof(struct _ocre_posix_utsname))) { + return -1; + } + + struct utsname info; + if (uname(&info) != 0) { + return -1; + } + + memset(name, 0, sizeof(struct _ocre_posix_utsname)); + + snprintf(name->sysname, OCRE_API_POSIX_BUF_SIZE, "%s (%s)", OCRE_SYSTEM_NAME, info.sysname); + snprintf(name->release, OCRE_API_POSIX_BUF_SIZE, "%s (%s)", APP_VERSION_STRING, info.release); + snprintf(name->version, OCRE_API_POSIX_BUF_SIZE, "%s", info.version); + +#ifdef CONFIG_ARM +#ifdef CONFIG_CPU_CORTEX_M0 + strlcat(name->machine, "ARM Cortex-M0", OCRE_API_POSIX_BUF_SIZE); +#elif CONFIG_CPU_CORTEX_M3 + strlcat(name->machine, "ARM Cortex-M3", OCRE_API_POSIX_BUF_SIZE); +#elif CONFIG_CPU_CORTEX_M4 + strlcat(name->machine, "ARM Cortex-M4", OCRE_API_POSIX_BUF_SIZE); +#elif CONFIG_CPU_CORTEX_M7 + strlcat(name->machine, "ARM Cortex-M7", OCRE_API_POSIX_BUF_SIZE); +#elif CONFIG_CPU_CORTEX_M33 + strlcat(name->machine, "ARM Cortex-M33", OCRE_API_POSIX_BUF_SIZE); +#elif CONFIG_CPU_CORTEX_M23 + strlcat(name->machine, "ARM Cortex-M23", OCRE_API_POSIX_BUF_SIZE); +#elif CONFIG_CPU_CORTEX_M55 + strlcat(name->machine, "ARM Cortex-M55", OCRE_API_POSIX_BUF_SIZE); +#endif +#else + strlcat(name->machine, info.machine, OCRE_API_POSIX_BUF_SIZE); +#endif + + strlcat(name->nodename, info.nodename, OCRE_API_POSIX_BUF_SIZE); + + return 0; +} + +int ocre_sleep(wasm_exec_env_t exec_env, int milliseconds) +{ + usleep(milliseconds * 1000); + return 0; +} + +// Ocre Runtime API +NativeSymbol ocre_api_table[] = { + {"uname", _ocre_posix_uname, "(*)i", NULL}, + {"ocre_sleep", ocre_sleep, "(i)i", NULL}, +#if defined(CONFIG_OCRE_TIMER) || defined(CONFIG_OCRE_GPIO) || defined(CONFIG_OCRE_SENSORS) || \ + defined(CONFIG_OCRE_CONTAINER_MESSAGING) + {"ocre_get_event", ocre_get_event, "(iiiiii)i", NULL}, + {"ocre_register_dispatcher", ocre_register_dispatcher, "(i$)i", NULL}, +#endif +// Container Messaging API +#ifdef CONFIG_OCRE_CONTAINER_MESSAGING + {"ocre_publish_message", ocre_messaging_publish, "(***i)i", NULL}, + {"ocre_subscribe_message", ocre_messaging_subscribe, "(*)i", NULL}, + {"ocre_messaging_free_module_event_data", ocre_messaging_free_module_event_data, "(iii)i", NULL}, +#endif +// Sensor API +#ifdef CONFIG_OCRE_SENSORS + {"ocre_sensors_init", ocre_sensors_init, "()i", NULL}, + {"ocre_sensors_discover", ocre_sensors_discover, "()i", NULL}, + {"ocre_sensors_open", ocre_sensors_open, "(i)i", NULL}, + {"ocre_sensors_get_handle", ocre_sensors_get_handle, "(i)i", NULL}, + {"ocre_sensors_get_channel_count", ocre_sensors_get_channel_count, "(i)i", NULL}, + {"ocre_sensors_get_channel_type", ocre_sensors_get_channel_type, "(ii)i", NULL}, + {"ocre_sensors_read", ocre_sensors_read, "(ii)F", NULL}, + {"ocre_sensors_open_by_name", ocre_sensors_open_by_name, "($)i", NULL}, + {"ocre_sensors_get_handle_by_name", ocre_sensors_get_handle_by_name, "($)i", NULL}, + {"ocre_sensors_get_channel_count_by_name", ocre_sensors_get_channel_count_by_name, "($)i", NULL}, + {"ocre_sensors_get_channel_type_by_name", ocre_sensors_get_channel_type_by_name, "($i)i", NULL}, + {"ocre_sensors_read_by_name", ocre_sensors_read_by_name, "($i)F", NULL}, + {"ocre_sensors_get_list", ocre_sensors_get_list, "($i)i", NULL}, +#endif +// Timer API +#ifdef CONFIG_OCRE_TIMER + {"ocre_timer_create", ocre_timer_create, "(i)i", NULL}, + {"ocre_timer_start", ocre_timer_start, "(iii)i", NULL}, + {"ocre_timer_stop", ocre_timer_stop, "(i)i", NULL}, + {"ocre_timer_delete", ocre_timer_delete, "(i)i", NULL}, + {"ocre_timer_get_remaining", ocre_timer_get_remaining, "(i)i", NULL}, +#endif +// GPIO API +#ifdef CONFIG_OCRE_GPIO + {"ocre_gpio_init", ocre_gpio_wasm_init, "()i", NULL}, + {"ocre_gpio_configure", ocre_gpio_wasm_configure, "(iii)i", NULL}, + {"ocre_gpio_pin_set", ocre_gpio_wasm_set, "(iii)i", NULL}, + {"ocre_gpio_pin_get", ocre_gpio_wasm_get, "(ii)i", NULL}, + {"ocre_gpio_pin_toggle", ocre_gpio_wasm_toggle, "(ii)i", NULL}, + {"ocre_gpio_register_callback", ocre_gpio_wasm_register_callback, "(ii)i", NULL}, + {"ocre_gpio_unregister_callback", ocre_gpio_wasm_unregister_callback, "(ii)i", NULL}, + + {"ocre_gpio_configure_by_name", ocre_gpio_wasm_configure_by_name, "($i)i", NULL}, + {"ocre_gpio_set_by_name", ocre_gpio_wasm_set_by_name, "($i)i", NULL}, + {"ocre_gpio_get_by_name", ocre_gpio_wasm_get_by_name, "($)i", NULL}, + {"ocre_gpio_toggle_by_name", ocre_gpio_wasm_toggle_by_name, "($)i", NULL}, + {"ocre_gpio_register_callback_by_name", ocre_gpio_wasm_register_callback_by_name, "($)i", NULL}, + {"ocre_gpio_unregister_callback_by_name", ocre_gpio_wasm_unregister_callback_by_name, "($)i", NULL}, +#endif +}; + +int ocre_api_table_size = sizeof(ocre_api_table) / sizeof(NativeSymbol); diff --git a/src/ocre/api/ocre_api.h b/src/runtime/wamr/ocre_api/ocre_api.h similarity index 67% rename from src/ocre/api/ocre_api.h rename to src/runtime/wamr/ocre_api/ocre_api.h index 391b5635..a0e8385f 100644 --- a/src/ocre/api/ocre_api.h +++ b/src/runtime/wamr/ocre_api/ocre_api.h @@ -17,12 +17,12 @@ #endif struct _ocre_posix_utsname { - char sysname[OCRE_API_POSIX_BUF_SIZE]; - char nodename[OCRE_API_POSIX_BUF_SIZE]; - char release[OCRE_API_POSIX_BUF_SIZE]; - char version[OCRE_API_POSIX_BUF_SIZE]; - char machine[OCRE_API_POSIX_BUF_SIZE]; - char domainname[OCRE_API_POSIX_BUF_SIZE]; + char sysname[OCRE_API_POSIX_BUF_SIZE]; + char nodename[OCRE_API_POSIX_BUF_SIZE]; + char release[OCRE_API_POSIX_BUF_SIZE]; + char version[OCRE_API_POSIX_BUF_SIZE]; + char machine[OCRE_API_POSIX_BUF_SIZE]; + char domainname[OCRE_API_POSIX_BUF_SIZE]; }; int _ocre_posix_uname(wasm_exec_env_t exec_env, struct _ocre_posix_utsname *name); diff --git a/src/runtime/wamr/ocre_api/ocre_common.c b/src/runtime/wamr/ocre_api/ocre_common.c new file mode 100644 index 00000000..a734b5fb --- /dev/null +++ b/src/runtime/wamr/ocre_api/ocre_common.c @@ -0,0 +1,385 @@ +/** + * @copyright Copyright © contributors to Project Ocre, + * which has been established as Project Ocre, a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// #include +#include +#include +#include +#include +#include +#include + +#include + +#include "core/core_external.h" + +LOG_MODULE_REGISTER(ocre_common, 4); + +#ifdef CONFIG_OCRE_GPIO +#include "ocre_gpio/ocre_gpio.h" +#endif + +#ifdef CONFIG_OCRE_CONTAINER_MESSAGING +#include "ocre_messaging/ocre_messaging.h" +#endif + +#include "ocre_common.h" + +typedef struct module_node { + ocre_module_context_t ctx; + core_snode_t node; +} module_node_t; + +static core_mutex_t registry_mutex; + +#define SIZE_OCRE_EVENT_BUFFER 32 + +/* Unified event queue implementation */ +core_eventq_t ocre_event_queue; +bool ocre_event_queue_initialized = false; +core_spinlock_t ocre_event_queue_lock; + +static struct cleanup_handler { + ocre_resource_type_t type; + ocre_cleanup_handler_t handler; +} cleanup_handlers[OCRE_RESOURCE_TYPE_COUNT]; + +bool common_initialized = false; + +/* Thread-Local Storage */ +__thread wasm_module_inst_t *current_module_tls = NULL; + +#if EVENT_THREAD_POOL_SIZE > 0 +// Arguments for event threads +struct event_thread_args { + int index; // Thread index for identification or logging +}; +static struct core_thread event_threads[EVENT_THREAD_POOL_SIZE]; +// Flag to signal event threads to exit gracefully +static volatile bool event_threads_exit = false; +static struct event_thread_args event_args[EVENT_THREAD_POOL_SIZE]; + +// Event thread function to process events from the ring buffer +static void event_thread_fn(void *arg1) +{ + struct event_thread_args *args = (struct event_thread_args *)arg1; + // Initialize WASM runtime thread environment + wasm_runtime_init_thread_env(); + // Main event processing loop + // Do something in wasm + // Saved for future usage + // Clean up WASM runtime thread envirnment + wasm_runtime_destroy_thread_env(); +} +#endif + +int ocre_get_event(wasm_exec_env_t exec_env, uint32_t type_offset, uint32_t id_offset, uint32_t port_offset, + uint32_t state_offset, uint32_t extra_offset, uint32_t payload_len_offset) +{ + wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); + if (!module_inst) { + LOG_ERR("No module instance for exec_env\n"); + return -EINVAL; + } + + uint32_t *type_native = (uint32_t *)wasm_runtime_addr_app_to_native(module_inst, type_offset); + uint32_t *id_native = (uint32_t *)wasm_runtime_addr_app_to_native(module_inst, id_offset); + uint32_t *port_native = (uint32_t *)wasm_runtime_addr_app_to_native(module_inst, port_offset); + uint32_t *state_native = (uint32_t *)wasm_runtime_addr_app_to_native(module_inst, state_offset); + uint32_t *extra_native = (uint32_t *)wasm_runtime_addr_app_to_native(module_inst, extra_offset); + uint32_t *payload_len_native = (uint32_t *)wasm_runtime_addr_app_to_native(module_inst, payload_len_offset); + + if (!type_native || !id_native || !port_native || !state_native || !extra_native || !payload_len_native) { + LOG_ERR("Invalid offsets provided"); + return -EINVAL; + } + + ocre_event_t event; + int ret; + + /* Generic event queue implementation for both platforms */ + core_spinlock_key_t key = core_spinlock_lock(&ocre_event_queue_lock); + ret = core_eventq_peek(&ocre_event_queue, &event); + if (ret != 0) { + core_spinlock_unlock(&ocre_event_queue_lock, key); + return -ENOMSG; + } + + if (event.owner != module_inst) { + core_spinlock_unlock(&ocre_event_queue_lock, key); + return -EPERM; + } + + ret = core_eventq_get(&ocre_event_queue, &event); + if (ret != 0) { + core_spinlock_unlock(&ocre_event_queue_lock, key); + return -ENOENT; + } + + // Send event correctly to WASM + switch (event.type) { + case OCRE_RESOURCE_TYPE_TIMER: { + LOG_DBG("Retrieved Timer event timer_id=%u, owner=%p", event.data.timer_event.timer_id, + (void *)event.owner); + *type_native = event.type; + *id_native = event.data.timer_event.timer_id; + *port_native = 0; + *state_native = 0; + *extra_native = 0; + *payload_len_native = 0; + break; + } + case OCRE_RESOURCE_TYPE_GPIO: { + LOG_DBG("Retrieved Gpio event pin_id=%u, port=%u, state=%u, owner=%p", + event.data.gpio_event.pin_id, event.data.gpio_event.port, event.data.gpio_event.state, + (void *)event.owner); + *type_native = event.type; + *id_native = event.data.gpio_event.pin_id; + *port_native = event.data.gpio_event.port; + *state_native = event.data.gpio_event.state; + *extra_native = 0; + *payload_len_native = 0; + break; + } + case OCRE_RESOURCE_TYPE_SENSOR: { + // Not used as we don't use callbacks in sensor API yet + break; + } + case OCRE_RESOURCE_TYPE_MESSAGING: { + LOG_DBG("Retrieved Messaging event: message_id=%u, topic=%s, " + "topic_offset=%u, content_type=%s, " + "content_type_offset=%u, payload_len=%d, owner=%p", + event.data.messaging_event.message_id, event.data.messaging_event.topic, + event.data.messaging_event.topic_offset, event.data.messaging_event.content_type, + event.data.messaging_event.content_type_offset, event.data.messaging_event.payload_len, + (void *)event.owner); + *type_native = event.type; + *id_native = event.data.messaging_event.message_id; + *port_native = event.data.messaging_event.topic_offset; + *state_native = event.data.messaging_event.content_type_offset; + *extra_native = event.data.messaging_event.payload_offset; + *payload_len_native = event.data.messaging_event.payload_len; + break; + } + /* + ================================= + Place to add more resource types + ================================= + */ + default: { + core_spinlock_unlock(&ocre_event_queue_lock, key); + LOG_ERR("Invalid event type: %u", event.type); + return -EINVAL; + } + } + core_spinlock_unlock(&ocre_event_queue_lock, key); + return 0; +} + +int ocre_common_init(void) +{ + static bool initialized = false; + if (initialized) { + LOG_INF("Common system already initialized"); + return 0; + } + + core_mutex_init(®istry_mutex); + + core_eventq_init(&ocre_event_queue, sizeof(ocre_event_t), SIZE_OCRE_EVENT_BUFFER); + + /* Purge any stale events from queue */ + ocre_event_t dummy; + while (core_eventq_get(&ocre_event_queue, &dummy) == 0) { + LOG_INF("Purged stale event from queue"); + } + + /* Temporary platform-specific initialization */ +#ifdef __ZEPHYR__ + /* No additional Zephyr-specific initialization needed */ +#else /* POSIX */ + pthread_mutex_init(&ocre_event_queue_lock.mutex, NULL); +#endif + + ocre_event_queue_initialized = true; +#if EVENT_THREAD_POOL_SIZE > 0 + LOG_INF("ocre_event_queue initialized at %p, size=%d", (void *)&ocre_event_queue, sizeof(ocre_event_t)); + for (int i = 0; i < EVENT_THREAD_POOL_SIZE; i++) { + event_args[i].index = i; + char thread_name[16]; + snprintf(thread_name, sizeof(thread_name), "event_thread_%d", i); + int ret = core_thread_create(&event_threads[i], event_thread_fn, &event_args[i], thread_name, + EVENT_THREAD_STACK_SIZE, 5); + if (ret != 0) { + LOG_ERR("Failed to create thread for event %d", i); + return -1; + } + LOG_INF("Started event thread %s", thread_name); + } +#endif + initialized = true; + common_initialized = true; + + LOG_INF("OCRE common initialized successfully"); + return 0; +} + +void ocre_common_shutdown(void) +{ +#if EVENT_THREAD_POOL_SIZE > 0 + event_threads_exit = true; + for (int i = EVENT_THREAD_POOL_SIZE; i > 0; i--) { + event_args[i].index = i; + char thread_name[16]; + snprintf(thread_name, sizeof(thread_name), "event_thread_%d", i); + core_thread_destroy(&event_threads[i]); + } +#endif + + core_eventq_destroy(&ocre_event_queue); + + common_initialized = false; + LOG_INF("OCRE common shutdown successfully"); +} + +int ocre_register_cleanup_handler(ocre_resource_type_t type, ocre_cleanup_handler_t handler) +{ + if (type >= OCRE_RESOURCE_TYPE_COUNT) { + LOG_ERR("Invalid resource type: %d", type); + return -EINVAL; + } + cleanup_handlers[type] = (struct cleanup_handler){type, handler}; + LOG_INF("Registered cleanup handler for type %d", type); + return 0; +} + +ocre_module_context_t *ocre_register_module(wasm_module_inst_t module_inst) +{ + if (!module_inst) { + LOG_ERR("Null module instance"); + return NULL; + } + ocre_module_context_t *ctx = malloc(sizeof(ocre_module_context_t)); + if (!ctx) { + LOG_ERR("Failed to allocate module context"); + return NULL; + } + ctx->inst = module_inst; + + ctx->in_use = true; + ctx->last_activity = core_uptime_get(); + memset(ctx->resource_count, 0, sizeof(ctx->resource_count)); + memset(ctx->dispatchers, 0, sizeof(ctx->dispatchers)); + + LOG_INF("Module registered: %p", (void *)module_inst); + return ctx; +} + +void ocre_unregister_module(wasm_module_inst_t module_inst) +{ + if (!module_inst) { + LOG_ERR("Null module instance"); + return; + } + + ocre_cleanup_module_resources(module_inst); + + ocre_module_context_t *ret = (ocre_module_context_t *)wasm_runtime_get_custom_data(module_inst); + free(ret); + + LOG_INF("Module unregistered: %p", (void *)module_inst); +} + +ocre_module_context_t *ocre_get_module_context(wasm_module_inst_t module_inst) +{ + if (!module_inst) { + LOG_ERR("Null module instance"); + return NULL; + } + + ocre_module_context_t *ret = (ocre_module_context_t *)wasm_runtime_get_custom_data(module_inst); + if (!ret) { + LOG_ERR("Module context not found for %p", (void *)module_inst); + return NULL; + } + return ret; +} + +int ocre_register_dispatcher(wasm_exec_env_t exec_env, ocre_resource_type_t type, const char *function_name) +{ + if (!exec_env || !function_name || type >= OCRE_RESOURCE_TYPE_COUNT) { + LOG_ERR("Invalid dispatcher params: exec_env=%p, type=%d, func=%s", (void *)exec_env, type, + function_name ? function_name : "null"); + return -EINVAL; + } + + wasm_module_inst_t module_inst = + current_module_tls ? *current_module_tls : wasm_runtime_get_module_inst(exec_env); + + if (!module_inst) { + LOG_ERR("No module instance for event type %d", type); + return -EINVAL; + } + ocre_module_context_t *ctx = ocre_get_module_context(module_inst); + if (!ctx) { + LOG_ERR("Module context not found for %p", (void *)module_inst); + return -EINVAL; + } + LOG_DBG("Attempting to lookup function '%s' in module %p", function_name, (void *)module_inst); + wasm_function_inst_t func = wasm_runtime_lookup_function(module_inst, function_name); + if (!func) { + LOG_ERR("Function %s not found in module %p", function_name, (void *)module_inst); + return -EINVAL; + } + core_mutex_lock(®istry_mutex); + ctx->dispatchers[type] = func; + core_mutex_unlock(®istry_mutex); + LOG_INF("Registered dispatcher for type %d: %s", type, function_name); + return 0; +} + +uint32_t ocre_get_resource_count(wasm_module_inst_t module_inst, ocre_resource_type_t type) +{ + ocre_module_context_t *ctx = ocre_get_module_context(module_inst); + return ctx ? ctx->resource_count[type] : 0; +} + +void ocre_increment_resource_count(wasm_module_inst_t module_inst, ocre_resource_type_t type) +{ + ocre_module_context_t *ctx = ocre_get_module_context(module_inst); + if (ctx && type < OCRE_RESOURCE_TYPE_COUNT) { + core_mutex_lock(®istry_mutex); + ctx->resource_count[type]++; + core_mutex_unlock(®istry_mutex); + LOG_INF("Incremented resource count: type=%d, count=%d", type, ctx->resource_count[type]); + } +} + +void ocre_decrement_resource_count(wasm_module_inst_t module_inst, ocre_resource_type_t type) +{ + ocre_module_context_t *ctx = ocre_get_module_context(module_inst); + if (ctx && type < OCRE_RESOURCE_TYPE_COUNT && ctx->resource_count[type] > 0) { + core_mutex_lock(®istry_mutex); + ctx->resource_count[type]--; + core_mutex_unlock(®istry_mutex); + LOG_INF("Decremented resource count: type=%d, count=%d", type, ctx->resource_count[type]); + } +} + +void ocre_cleanup_module_resources(wasm_module_inst_t module_inst) +{ + for (int i = 0; i < OCRE_RESOURCE_TYPE_COUNT; i++) { + if (cleanup_handlers[i].handler) { + cleanup_handlers[i].handler(module_inst); + } + } +} + +wasm_module_inst_t ocre_get_current_module(void) +{ + return current_module_tls ? *current_module_tls : NULL; +} diff --git a/src/ocre/api/ocre_common.h b/src/runtime/wamr/ocre_api/ocre_common.h similarity index 59% rename from src/ocre/api/ocre_common.h rename to src/runtime/wamr/ocre_api/ocre_common.h index 95be03a9..71a3649e 100644 --- a/src/ocre/api/ocre_common.h +++ b/src/runtime/wamr/ocre_api/ocre_common.h @@ -8,48 +8,49 @@ #ifndef OCRE_COMMON_H #define OCRE_COMMON_H -#include +#include "core/core_external.h" +#include "ocre_messaging/ocre_messaging.h" #include #include -#include "ocre_core_external.h" -#include "../ocre_messaging/ocre_messaging.h" +#include #define OCRE_EVENT_THREAD_STACK_SIZE 2048 #define OCRE_EVENT_THREAD_PRIORITY 5 -#define OCRE_WASM_STACK_SIZE 16384 -#define EVENT_THREAD_POOL_SIZE 0 +#define OCRE_WASM_STACK_SIZE 16384 +#define EVENT_THREAD_POOL_SIZE 0 extern bool common_initialized; extern bool ocre_event_queue_initialized; extern __thread wasm_module_inst_t *current_module_tls; -extern char *ocre_event_queue_buffer_ptr; // Defined in ocre_common.c +extern char *ocre_event_queue_buffer_ptr; // Defined in ocre_common.c /* External declarations for unified event queue */ -extern core_eventq_t ocre_event_queue; // Defined in ocre_common.c -extern core_spinlock_t ocre_event_queue_lock; // Defined in ocre_common.c - +extern core_eventq_t ocre_event_queue; // Defined in ocre_common.c +extern core_spinlock_t ocre_event_queue_lock; // Defined in ocre_common.c /** * @brief Enumeration of OCRE resource types. */ typedef enum { - OCRE_RESOURCE_TYPE_TIMER, ///< Timer resource - OCRE_RESOURCE_TYPE_GPIO, ///< GPIO resource - OCRE_RESOURCE_TYPE_SENSOR, ///< Sensor resource - OCRE_RESOURCE_TYPE_MESSAGING, ///< Messaging resource - OCRE_RESOURCE_TYPE_COUNT ///< Total number of resource types + OCRE_RESOURCE_TYPE_TIMER, ///< Timer resource + OCRE_RESOURCE_TYPE_GPIO, ///< GPIO resource + OCRE_RESOURCE_TYPE_SENSOR, ///< Sensor resource + OCRE_RESOURCE_TYPE_MESSAGING, ///< Messaging resource + OCRE_RESOURCE_TYPE_COUNT ///< Total number of resource types } ocre_resource_type_t; /** * @brief Structure representing the context of an OCRE module. */ typedef struct { - wasm_module_inst_t inst; ///< WASM module instance - wasm_exec_env_t exec_env; ///< WASM execution environment - bool in_use; ///< Flag indicating if the module is in use - uint32_t last_activity; ///< Timestamp of the last activity - uint32_t resource_count[OCRE_RESOURCE_TYPE_COUNT]; ///< Count of resources per type - wasm_function_inst_t dispatchers[OCRE_RESOURCE_TYPE_COUNT]; ///< Event dispatchers per resource type + wasm_module_inst_t inst; ///< WASM module instance + // wasm_exec_env_t exec_env; ///< WASM execution + // environment + bool in_use; ///< Flag indicating if the module is in use + uint32_t last_activity; ///< Timestamp of the last activity + uint32_t resource_count[OCRE_RESOURCE_TYPE_COUNT]; ///< Count of resources per type + wasm_function_inst_t dispatchers[OCRE_RESOURCE_TYPE_COUNT]; ///< Event dispatchers per resource + ///< type } ocre_module_context_t; /** @@ -63,38 +64,38 @@ typedef void (*ocre_cleanup_handler_t)(wasm_module_inst_t module_inst); * @brief Structure representing an OCRE event for dispatching. */ typedef struct { - union { - struct { - uint32_t timer_id; ///< Timer ID - } timer_event; ///< Timer event data - struct { - uint32_t pin_id; ///< GPIO pin ID - uint32_t port; ///< GPIO port - uint32_t state; ///< GPIO state - } gpio_event; ///< GPIO event data - struct { - uint32_t sensor_id; ///< Sensor ID - uint32_t channel; ///< Sensor channel - uint32_t value; ///< Sensor value - } sensor_event; ///< Sensor event data - struct { - uint32_t message_id; ///< Message ID - char *topic; ///< Message topic - uint32_t topic_offset; ///< Message topic offset - char *content_type; ///< Message content type - uint32_t content_type_offset; ///< Message content type offset - void *payload; ///< Message payload - uint32_t payload_offset; ///< Message payload offset - uint32_t payload_len; ///< Payload length - } messaging_event; ///< Messaging event data - /* - ============================= - Place to add more event data - ============================= - */ - } data; ///< Union of event data - wasm_module_inst_t owner; ///< Owner module instance - ocre_resource_type_t type; ///< Type of the event + union { + struct { + uint32_t timer_id; ///< Timer ID + } timer_event; ///< Timer event data + struct { + uint32_t pin_id; ///< GPIO pin ID + uint32_t port; ///< GPIO port + uint32_t state; ///< GPIO state + } gpio_event; ///< GPIO event data + struct { + uint32_t sensor_id; ///< Sensor ID + uint32_t channel; ///< Sensor channel + uint32_t value; ///< Sensor value + } sensor_event; ///< Sensor event data + struct { + uint32_t message_id; ///< Message ID + char *topic; ///< Message topic + uint32_t topic_offset; ///< Message topic offset + char *content_type; ///< Message content type + uint32_t content_type_offset; ///< Message content type offset + void *payload; ///< Message payload + uint32_t payload_offset; ///< Message payload offset + uint32_t payload_len; ///< Payload length + } messaging_event; ///< Messaging event data + /* + ============================= + Place to add more event data + ============================= + */ + } data; ///< Union of event data + wasm_module_inst_t owner; ///< Owner module instance + ocre_resource_type_t type; ///< Type of the event } ocre_event_t; /** @@ -112,7 +113,7 @@ int ocre_common_init(void); * @param module_inst The WASM module instance to register. * @return 0 on success, negative error code on failure. */ -int ocre_register_module(wasm_module_inst_t module_inst); +ocre_module_context_t *ocre_register_module(wasm_module_inst_t module_inst); /** * @brief Unregister a WASM module from the OCRE system. @@ -200,7 +201,7 @@ wasm_module_inst_t ocre_get_current_module(void); * @return 0 on success, negative error code on failure. */ int ocre_get_event(wasm_exec_env_t exec_env, uint32_t type_offset, uint32_t id_offset, uint32_t port_offset, - uint32_t state_offset, uint32_t extra_offset, uint32_t payload_len_offset); + uint32_t state_offset, uint32_t extra_offset, uint32_t payload_len_offset); void ocre_common_shutdown(void); diff --git a/src/ocre/ocre_gpio/ocre_gpio.c b/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.c similarity index 99% rename from src/ocre/ocre_gpio/ocre_gpio.c rename to src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.c index 63004048..4e3af14e 100644 --- a/src/ocre/ocre_gpio/ocre_gpio.c +++ b/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.c @@ -5,16 +5,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include +// #include +// #include +// #include #include #include #include #include #include -LOG_MODULE_DECLARE(ocre_cs_component, OCRE_LOG_LEVEL); +LOG_MODULE_REGISTER(ocre_gpio, 4); typedef struct { uint32_t in_use: 1; diff --git a/src/ocre/ocre_gpio/ocre_gpio.h b/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.h similarity index 100% rename from src/ocre/ocre_gpio/ocre_gpio.h rename to src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.h diff --git a/src/runtime/wamr/ocre_api/ocre_messaging/ocre_messaging.c b/src/runtime/wamr/ocre_api/ocre_messaging/ocre_messaging.c new file mode 100644 index 00000000..f726a659 --- /dev/null +++ b/src/runtime/wamr/ocre_api/ocre_messaging/ocre_messaging.c @@ -0,0 +1,280 @@ +/** + * @copyright Copyright © contributors to Project Ocre, + * which has been established as Project Ocre, a Series of LF Projects, LLC + * + * SPDX-License-License: Apache-2.0 + */ + +#include + +#include + +#include "../core/core_external.h" +#include "ocre_messaging.h" +#include "../ocre_common.h" + +LOG_MODULE_REGISTER(ocre_messaging, 4); + +#ifndef CONFIG_OCRE_MESSAGING_MAX_SUBSCRIPTIONS +#define CONFIG_OCRE_MESSAGING_MAX_SUBSCRIPTIONS 10 +#endif + +#define OCRE_MAX_TOPIC_LEN 64 + +/* Messaging subscription structure */ +typedef struct { + char topic[OCRE_MAX_TOPIC_LEN]; + wasm_module_inst_t module_inst; + bool is_active; +} ocre_messaging_subscription_t; + +typedef struct { + ocre_messaging_subscription_t subscriptions[CONFIG_OCRE_MESSAGING_MAX_SUBSCRIPTIONS]; + uint16_t subscription_count; + core_mutex_t mutex; +} ocre_messaging_system_t; + +static ocre_messaging_system_t messaging_system = {0}; +static bool messaging_system_initialized = false; + +/* Initialize messaging system */ +int ocre_messaging_init(void) +{ + if (messaging_system_initialized) { + LOG_INF("Messaging system already initialized"); + return 0; + } + + memset(&messaging_system, 0, sizeof(ocre_messaging_system_t)); + + core_mutex_init(&messaging_system.mutex); + + ocre_register_cleanup_handler(OCRE_RESOURCE_TYPE_MESSAGING, ocre_messaging_cleanup_container); + messaging_system_initialized = true; + LOG_INF("Messaging system initialized"); + return 0; +} + +/* Cleanup messaging resources for a module */ +void ocre_messaging_cleanup_container(wasm_module_inst_t module_inst) +{ + if (!messaging_system_initialized || !module_inst) { + return; + } + + core_mutex_lock(&messaging_system.mutex); + + for (int i = 0; i < CONFIG_OCRE_MESSAGING_MAX_SUBSCRIPTIONS; i++) { + if (messaging_system.subscriptions[i].is_active && + messaging_system.subscriptions[i].module_inst == module_inst) { + messaging_system.subscriptions[i].is_active = false; + messaging_system.subscriptions[i].module_inst = NULL; + messaging_system.subscriptions[i].topic[0] = '\0'; + messaging_system.subscription_count--; + ocre_decrement_resource_count(module_inst, OCRE_RESOURCE_TYPE_MESSAGING); + LOG_DBG("Cleaned up subscription %d for module %p", i, (void *)module_inst); + } + } + + core_mutex_unlock(&messaging_system.mutex); + + LOG_DBG("Cleaned up messaging resources for module %p", (void *)module_inst); +} + +/* Subscribe to a topic */ +int ocre_messaging_subscribe(wasm_exec_env_t exec_env, void *topic) +{ + if (!messaging_system_initialized) { + if (ocre_messaging_init() != 0) { + LOG_ERR("Failed to initialize messaging system"); + return -EINVAL; + } + } + + if (!topic || ((char *)topic)[0] == '\0') { + LOG_ERR("Topic is NULL or empty"); + return -EINVAL; + } + + wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); + if (!module_inst) { + LOG_ERR("No module instance for exec_env"); + return -EINVAL; + } + + ocre_module_context_t *ctx = ocre_get_module_context(module_inst); + if (!ctx) { + LOG_ERR("Module context not found for module instance %p", (void *)module_inst); + return -EINVAL; + } + + core_mutex_lock(&messaging_system.mutex); + + // Check if already subscribed + for (int i = 0; i < CONFIG_OCRE_MESSAGING_MAX_SUBSCRIPTIONS; i++) { + if (messaging_system.subscriptions[i].is_active && + messaging_system.subscriptions[i].module_inst == module_inst && + strcmp(messaging_system.subscriptions[i].topic, (char *)topic) == 0) { + LOG_INF("Already subscribed to topic: %s", (char *)topic); + core_mutex_unlock(&messaging_system.mutex); + return 0; + } + } + + // Find a free slot + for (int i = 0; i < CONFIG_OCRE_MESSAGING_MAX_SUBSCRIPTIONS; i++) { + if (!messaging_system.subscriptions[i].is_active) { + strncpy(messaging_system.subscriptions[i].topic, (char *)topic, OCRE_MAX_TOPIC_LEN - 1); + messaging_system.subscriptions[i].topic[OCRE_MAX_TOPIC_LEN - 1] = '\0'; + messaging_system.subscriptions[i].module_inst = module_inst; + messaging_system.subscriptions[i].is_active = true; + messaging_system.subscription_count++; + ocre_increment_resource_count(module_inst, OCRE_RESOURCE_TYPE_MESSAGING); + LOG_INF("Subscribed to topic: %s, module: %p", (char *)topic, (void *)module_inst); + core_mutex_unlock(&messaging_system.mutex); + return 0; + } + } + + core_mutex_unlock(&messaging_system.mutex); + + LOG_ERR("No free subscription slots available"); + return -ENOMEM; +} + +/* Publish a message */ +int ocre_messaging_publish(wasm_exec_env_t exec_env, void *topic, void *content_type, void *payload, int payload_len) +{ + if (!messaging_system_initialized) { + if (ocre_messaging_init() != 0) { + LOG_ERR("Failed to initialize messaging system"); + return -EINVAL; + } + } + + if (!topic || ((char *)topic)[0] == '\0') { + LOG_ERR("Topic is NULL or empty"); + return -EINVAL; + } + if (!content_type || ((char *)content_type)[0] == '\0') { + LOG_ERR("Content type is NULL or empty"); + return -EINVAL; + } + if (!payload || payload_len <= 0) { + LOG_ERR("Payload is NULL or payload_len is invalid"); + return -EINVAL; + } + + wasm_module_inst_t publisher_module = wasm_runtime_get_module_inst(exec_env); + if (!publisher_module) { + LOG_ERR("No module instance for exec_env"); + return -EINVAL; + } + + static uint32_t message_id = 0; + bool message_sent = false; + + core_mutex_lock(&messaging_system.mutex); + + // Find matching subscriptions + for (int i = 0; i < CONFIG_OCRE_MESSAGING_MAX_SUBSCRIPTIONS; i++) { + if (!messaging_system.subscriptions[i].is_active) { + continue; + } + + // Check if the published topic matches the subscription (prefix match) + const char *subscribed_topic = messaging_system.subscriptions[i].topic; + size_t subscribed_len = strlen(subscribed_topic); + + if (strncmp(subscribed_topic, (char *)topic, subscribed_len) != 0) { + continue; // No prefix match + } + + wasm_module_inst_t target_module = messaging_system.subscriptions[i].module_inst; + if (!target_module) { + LOG_ERR("Invalid module instance for subscription %d", i); + continue; + } + + // Allocate WASM memory for the target module + uint32_t topic_offset = + (uint32_t)wasm_runtime_module_dup_data(target_module, (char *)topic, strlen((char *)topic) + 1); + if (topic_offset == 0) { + LOG_ERR("Failed to allocate WASM memory for topic"); + continue; + } + + uint32_t content_offset = (uint32_t)wasm_runtime_module_dup_data(target_module, (char *)content_type, + strlen((char *)content_type) + 1); + if (content_offset == 0) { + LOG_ERR("Failed to allocate WASM memory for content_type"); + wasm_runtime_module_free(target_module, topic_offset); + continue; + } + + uint32_t payload_offset = (uint32_t)wasm_runtime_module_dup_data(target_module, payload, payload_len); + if (payload_offset == 0) { + LOG_ERR("Failed to allocate WASM memory for payload"); + wasm_runtime_module_free(target_module, topic_offset); + wasm_runtime_module_free(target_module, content_offset); + continue; + } + + // Create and queue the messaging event + ocre_event_t event; + event.type = OCRE_RESOURCE_TYPE_MESSAGING; + event.data.messaging_event.message_id = message_id; + event.data.messaging_event.topic = topic; + event.data.messaging_event.topic_offset = topic_offset; + event.data.messaging_event.content_type = content_type; + event.data.messaging_event.content_type_offset = content_offset; + event.data.messaging_event.payload = payload; + event.data.messaging_event.payload_offset = payload_offset; + event.data.messaging_event.payload_len = (uint32_t)payload_len; + event.owner = target_module; + + LOG_DBG("Creating messaging event: ID=%d, topic=%s, content_type=%s, payload_len=%d for module %p", + message_id, (char *)topic, (char *)content_type, payload_len, (void *)target_module); + + core_spinlock_key_t key = core_spinlock_lock(&ocre_event_queue_lock); + if (core_eventq_put(&ocre_event_queue, &event) != 0) { + LOG_ERR("Failed to queue messaging event for message ID %d", message_id); + wasm_runtime_module_free(target_module, topic_offset); + wasm_runtime_module_free(target_module, content_offset); + wasm_runtime_module_free(target_module, payload_offset); + } else { + message_sent = true; + LOG_DBG("Queued messaging event for message ID %d", message_id); + } + core_spinlock_unlock(&ocre_event_queue_lock, key); + } + + core_mutex_unlock(&messaging_system.mutex); + + if (message_sent) { + LOG_DBG("Published message: ID=%d, topic=%s, content_type=%s, payload_len=%d", message_id, + (char *)topic, (char *)content_type, payload_len); + message_id++; + return 0; + } else { + LOG_WRN("No matching subscriptions found for topic %s", (char *)topic); + return -ENOENT; + } +} + +/* Free module event data */ +int ocre_messaging_free_module_event_data(wasm_exec_env_t exec_env, uint32_t topic_offset, uint32_t content_offset, + uint32_t payload_offset) +{ + wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); + if (!module_inst) { + LOG_ERR("Cannot find module_inst for free event data"); + return -EINVAL; + } + + wasm_runtime_module_free(module_inst, topic_offset); + wasm_runtime_module_free(module_inst, content_offset); + wasm_runtime_module_free(module_inst, payload_offset); + + return 0; +} diff --git a/src/ocre/ocre_messaging/ocre_messaging.h b/src/runtime/wamr/ocre_api/ocre_messaging/ocre_messaging.h similarity index 84% rename from src/ocre/ocre_messaging/ocre_messaging.h rename to src/runtime/wamr/ocre_api/ocre_messaging/ocre_messaging.h index d46eb56e..34f13267 100644 --- a/src/ocre/ocre_messaging/ocre_messaging.h +++ b/src/runtime/wamr/ocre_api/ocre_messaging/ocre_messaging.h @@ -8,8 +8,7 @@ #ifndef OCRE_MESSAGING_H #define OCRE_MESSAGING_H -#include -#include "ocre_core_external.h" +#include #include #define MESSAGING_QUEUE_SIZE 100 @@ -18,11 +17,11 @@ * @brief Structure representing an OCRE message. */ typedef struct { - uint32_t mid; ///< Message ID - void *topic; ///< Topic of the message (pointer to string) - void *content_type; ///< Content type (e.g., MIME type, pointer to string) - void *payload; ///< Message payload - uint32_t payload_len; ///< Length of the payload + uint32_t mid; ///< Message ID + void *topic; ///< Topic of the message (pointer to string) + void *content_type; ///< Content type (e.g., MIME type, pointer to string) + void *payload; ///< Message payload + uint32_t payload_len; ///< Length of the payload } ocre_msg_t; /** @@ -73,6 +72,6 @@ void ocre_messaging_cleanup_container(wasm_module_inst_t module_inst); * @return OCRE_SUCCESS on success, negative error code on failure. */ int ocre_messaging_free_module_event_data(wasm_exec_env_t exec_env, uint32_t topic_offset, uint32_t content_offset, - uint32_t payload_offset); + uint32_t payload_offset); #endif /* OCRE_MESSAGING_H */ diff --git a/src/ocre/ocre_sensors/custom,rng-sensor.yaml b/src/runtime/wamr/ocre_api/ocre_sensors/custom,rng-sensor.yaml similarity index 100% rename from src/ocre/ocre_sensors/custom,rng-sensor.yaml rename to src/runtime/wamr/ocre_api/ocre_sensors/custom,rng-sensor.yaml diff --git a/src/ocre/ocre_sensors/ocre_sensors.c b/src/runtime/wamr/ocre_api/ocre_sensors/ocre_sensors.c similarity index 99% rename from src/ocre/ocre_sensors/ocre_sensors.c rename to src/runtime/wamr/ocre_api/ocre_sensors/ocre_sensors.c index e2d36dd8..03358e9b 100644 --- a/src/ocre/ocre_sensors/ocre_sensors.c +++ b/src/runtime/wamr/ocre_api/ocre_sensors/ocre_sensors.c @@ -9,7 +9,7 @@ #include #include #include -LOG_MODULE_DECLARE(ocre_sensors, OCRE_LOG_LEVEL); +LOG_MODULE_REGISTER(ocre_sensors, 4); #include "ocre_sensors.h" diff --git a/src/ocre/ocre_sensors/ocre_sensors.h b/src/runtime/wamr/ocre_api/ocre_sensors/ocre_sensors.h similarity index 100% rename from src/ocre/ocre_sensors/ocre_sensors.h rename to src/runtime/wamr/ocre_api/ocre_sensors/ocre_sensors.h diff --git a/src/ocre/ocre_sensors/rng_sensor.c b/src/runtime/wamr/ocre_api/ocre_sensors/rng_sensor.c similarity index 100% rename from src/ocre/ocre_sensors/rng_sensor.c rename to src/runtime/wamr/ocre_api/ocre_sensors/rng_sensor.c diff --git a/src/ocre/ocre_sensors/rng_sensor.h b/src/runtime/wamr/ocre_api/ocre_sensors/rng_sensor.h similarity index 100% rename from src/ocre/ocre_sensors/rng_sensor.h rename to src/runtime/wamr/ocre_api/ocre_sensors/rng_sensor.h diff --git a/src/ocre/ocre_sensors/usage.md b/src/runtime/wamr/ocre_api/ocre_sensors/usage.md similarity index 100% rename from src/ocre/ocre_sensors/usage.md rename to src/runtime/wamr/ocre_api/ocre_sensors/usage.md diff --git a/src/runtime/wamr/ocre_api/ocre_timers/ocre_timer.c b/src/runtime/wamr/ocre_api/ocre_timers/ocre_timer.c new file mode 100644 index 00000000..5c14a279 --- /dev/null +++ b/src/runtime/wamr/ocre_api/ocre_timers/ocre_timer.c @@ -0,0 +1,263 @@ +/** + * @copyright Copyright © contributors to Project Ocre, + * which has been established as Project Ocre, a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include + +#include + +#include "../core/core_external.h" +#include "../core/core_internal.h" +#include "../ocre_common.h" +#include "ocre_timer.h" + +LOG_MODULE_REGISTER(ocre_timer, 4); + +/* Unified timer structure using core_timer API */ +typedef struct { + uint32_t in_use : 1; + uint32_t id : 8; // Up to 256 timers + uint32_t interval : 16; // Up to 65s intervals + uint32_t periodic : 1; + uint32_t running : 1; // Track if timer is currently running + uint32_t start_time; // Start time for remaining time calculations + core_timer_t timer; // Unified core timer + wasm_module_inst_t owner; +} ocre_timer_internal; + +#ifndef CONFIG_OCRE_MAX_TIMERS +#define CONFIG_OCRE_MAX_TIMERS 5 +#endif + +// Static data +static ocre_timer_internal timers[CONFIG_OCRE_MAX_TIMERS]; +static bool timer_system_initialized = false; + +static void unified_timer_callback(void *user_data); + +void ocre_timer_init(void) +{ + if (timer_system_initialized) { + LOG_INF("Timer system already initialized"); + return; + } + + ocre_register_cleanup_handler(OCRE_RESOURCE_TYPE_TIMER, ocre_timer_cleanup_container); + timer_system_initialized = true; + LOG_INF("Timer system initialized"); +} + +int ocre_timer_create(wasm_exec_env_t exec_env, int id) +{ + wasm_module_inst_t module = wasm_runtime_get_module_inst(exec_env); + if (!module || id <= 0 || id > CONFIG_OCRE_MAX_TIMERS) { + LOG_ERR("Invalid module %p or timer ID %d (max: %d)", (void *)module, id, CONFIG_OCRE_MAX_TIMERS); + return -EINVAL; + } + + ocre_timer_internal *timer = &timers[id - 1]; + if (timer->in_use) { + LOG_ERR("Timer ID %d already in use", id); + return -EBUSY; + } + + timer->id = id; + timer->owner = module; + timer->in_use = 1; + + // Initialize unified core timer + if (core_timer_init(&timer->timer, unified_timer_callback, timer) != 0) { + LOG_ERR("Failed to initialize core timer %d", id); + timer->in_use = 0; + return -EINVAL; + } + + ocre_increment_resource_count(module, OCRE_RESOURCE_TYPE_TIMER); + LOG_INF("Created timer %d for module %p", id, (void *)module); + return 0; +} + +int ocre_timer_delete(wasm_exec_env_t exec_env, ocre_timer_t id) +{ + wasm_module_inst_t module = wasm_runtime_get_module_inst(exec_env); + if (!module || id <= 0 || id > CONFIG_OCRE_MAX_TIMERS) { + LOG_ERR("Invalid module %p or timer ID %d", (void *)module, id); + return -EINVAL; + } + + ocre_timer_internal *timer = &timers[id - 1]; + if (!timer->in_use || timer->owner != module) { + LOG_ERR("Timer ID %d not in use or not owned by module %p", id, (void *)module); + return -EINVAL; + } + + // Stop unified core timer + core_timer_stop(&timer->timer); + + timer->in_use = 0; + timer->running = 0; + timer->owner = NULL; + ocre_decrement_resource_count(module, OCRE_RESOURCE_TYPE_TIMER); + LOG_INF("Deleted timer %d", id); + return 0; +} + +int ocre_timer_start(wasm_exec_env_t exec_env, ocre_timer_t id, int interval, int is_periodic) +{ + wasm_module_inst_t module = wasm_runtime_get_module_inst(exec_env); + if (!module || id <= 0 || id > CONFIG_OCRE_MAX_TIMERS) { + LOG_ERR("Invalid module %p or timer ID %d", (void *)module, id); + return -EINVAL; + } + + ocre_timer_internal *timer = &timers[id - 1]; + if (!timer->in_use || timer->owner != module) { + LOG_ERR("Timer ID %d not in use or not owned by module %p", id, (void *)module); + return -EINVAL; + } + + if (interval <= 0 || interval > 65535) { + LOG_ERR("Invalid interval %dms (must be 1-65535ms)", interval); + return -EINVAL; + } + + timer->interval = interval; + timer->periodic = is_periodic; + timer->start_time = core_uptime_get(); + timer->running = 1; + + // Start unified core timer + int period_ms = is_periodic ? interval : 0; + if (core_timer_start(&timer->timer, interval, period_ms) != 0) { + LOG_ERR("Failed to start core timer %d", id); + timer->running = 0; + return -EINVAL; + } + + LOG_INF("Started timer %d with interval %dms, periodic=%d", id, interval, is_periodic); + return 0; +} + +int ocre_timer_stop(wasm_exec_env_t exec_env, ocre_timer_t id) +{ + wasm_module_inst_t module = wasm_runtime_get_module_inst(exec_env); + if (!module || id <= 0 || id > CONFIG_OCRE_MAX_TIMERS) { + LOG_ERR("Invalid module %p or timer ID %d", (void *)module, id); + return -EINVAL; + } + + ocre_timer_internal *timer = &timers[id - 1]; + if (!timer->in_use || timer->owner != module) { + LOG_ERR("Timer ID %d not in use or not owned by module %p", id, (void *)module); + return -EINVAL; + } + + // Stop unified core timer + core_timer_stop(&timer->timer); + timer->running = 0; + + LOG_INF("Stopped timer %d", id); + return 0; +} + +int ocre_timer_get_remaining(wasm_exec_env_t exec_env, ocre_timer_t id) +{ + wasm_module_inst_t module = wasm_runtime_get_module_inst(exec_env); + if (!module || id <= 0 || id > CONFIG_OCRE_MAX_TIMERS) { + LOG_ERR("Invalid module %p or timer ID %d", (void *)module, id); + return -EINVAL; + } + + ocre_timer_internal *timer = &timers[id - 1]; + if (!timer->in_use || timer->owner != module) { + LOG_ERR("Timer ID %d not in use or not owned by module %p", id, (void *)module); + return -EINVAL; + } + + int remaining; + if (!timer->running) { + remaining = 0; + } else { + uint32_t current_time = core_uptime_get(); + uint32_t elapsed = current_time - timer->start_time; + if (elapsed >= timer->interval) { + remaining = 0; // Timer should have expired + } else { + remaining = timer->interval - elapsed; + } + } + + LOG_INF("Timer %d remaining time: %dms", id, remaining); + return remaining; +} + +void ocre_timer_cleanup_container(wasm_module_inst_t module_inst) +{ + if (!module_inst) { + LOG_ERR("Invalid module instance for cleanup"); + return; + } + + for (int i = 0; i < CONFIG_OCRE_MAX_TIMERS; i++) { + if (timers[i].in_use && timers[i].owner == module_inst) { + // Stop unified core timer + core_timer_stop(&timers[i].timer); + timers[i].in_use = 0; + timers[i].running = 0; + timers[i].owner = NULL; + ocre_decrement_resource_count(module_inst, OCRE_RESOURCE_TYPE_TIMER); + LOG_DBG("Cleaned up timer %d for module %p", i + 1, (void *)module_inst); + } + } + LOG_DBG("Cleaned up timer resources for module %p", (void *)module_inst); +} + +/* Unified timer callback using core_timer API */ +static void unified_timer_callback(void *user_data) +{ + if (!timer_system_initialized || !common_initialized || !ocre_event_queue_initialized) { + LOG_ERR("Timer, common, or event queue not initialized, skipping callback"); + return; + } + + ocre_timer_internal *timer = (ocre_timer_internal *)user_data; + if (!timer || !timer->in_use || !timer->owner) { + LOG_ERR("Invalid timer in callback: %p", (void *)timer); + return; + } + + LOG_DBG("Timer callback for timer %d", timer->id); + + // For non-periodic timers, mark as not running + if (!timer->periodic) { + timer->running = 0; + } else { + // For periodic timers, update start time for next cycle + timer->start_time = core_uptime_get(); + } + + // Create and queue timer event + ocre_event_t event; + event.type = OCRE_RESOURCE_TYPE_TIMER; + event.data.timer_event.timer_id = timer->id; + event.owner = timer->owner; + + LOG_DBG("Creating timer event: type=%d, id=%d, for owner %p", event.type, timer->id, (void *)timer->owner); + + core_spinlock_key_t key = core_spinlock_lock(&ocre_event_queue_lock); + if (core_eventq_put(&ocre_event_queue, &event) != 0) { + LOG_ERR("Failed to queue timer event for timer %d", timer->id); + } else { + LOG_DBG("Queued timer event for timer %d", timer->id); + } + core_spinlock_unlock(&ocre_event_queue_lock, key); +} diff --git a/src/ocre/ocre_timers/ocre_timer.h b/src/runtime/wamr/ocre_api/ocre_timers/ocre_timer.h similarity index 98% rename from src/ocre/ocre_timers/ocre_timer.h rename to src/runtime/wamr/ocre_api/ocre_timers/ocre_timer.h index 1cdf1289..d922d4a3 100644 --- a/src/ocre/ocre_timers/ocre_timer.h +++ b/src/runtime/wamr/ocre_api/ocre_timers/ocre_timer.h @@ -9,7 +9,6 @@ #define OCRE_TIMER_H #include -#include "ocre_core_external.h" typedef int ocre_timer_t; diff --git a/src/ocre/utils/strlcat.c b/src/runtime/wamr/ocre_api/utils/strlcat.c similarity index 63% rename from src/ocre/utils/strlcat.c rename to src/runtime/wamr/ocre_api/utils/strlcat.c index f3597793..57c3c37b 100644 --- a/src/ocre/utils/strlcat.c +++ b/src/runtime/wamr/ocre_api/utils/strlcat.c @@ -26,32 +26,29 @@ * Returns strlen(src) + MIN(dsize, strlen(initial dst)). * If retval >= dsize, truncation occurred. */ -size_t -strlcat (char *dst, - const char *src, - size_t dsize) +size_t strlcat(char *dst, const char *src, size_t dsize) { - const char *odst = dst; - const char *osrc = src; - size_t n = dsize; - size_t dlen; + const char *odst = dst; + const char *osrc = src; + size_t n = dsize; + size_t dlen; - /* Find the end of dst and adjust bytes left but don't go past end. */ - while (n-- != 0 && *dst != '\0') - dst++; - dlen = dst - odst; - n = dsize - dlen; + /* Find the end of dst and adjust bytes left but don't go past end. */ + while (n-- != 0 && *dst != '\0') + dst++; + dlen = dst - odst; + n = dsize - dlen; - if (n-- == 0) - return(dlen + strlen(src)); - while (*src != '\0') { - if (n != 0) { - *dst++ = *src; - n--; - } - src++; - } - *dst = '\0'; + if (n-- == 0) + return (dlen + strlen(src)); + while (*src != '\0') { + if (n != 0) { + *dst++ = *src; + n--; + } + src++; + } + *dst = '\0'; - return(dlen + (src - osrc)); /* count does not include NUL */ + return (dlen + (src - osrc)); /* count does not include NUL */ } diff --git a/src/ocre/utils/utils.h b/src/runtime/wamr/ocre_api/utils/strlcat.h similarity index 62% rename from src/ocre/utils/utils.h rename to src/runtime/wamr/ocre_api/utils/strlcat.h index 3c46ba2f..c0c3e22e 100644 --- a/src/ocre/utils/utils.h +++ b/src/runtime/wamr/ocre_api/utils/strlcat.h @@ -1,13 +1,3 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef OCRE_UTILS_H_ -#define OCRE_UTILS_H_ - #include /* @@ -18,5 +8,3 @@ * If retval >= dsize, truncation occurred. */ size_t strlcat(char *dst, const char *src, size_t dsize); - -#endif diff --git a/src/runtime/wamr/wamr.c b/src/runtime/wamr/wamr.c new file mode 100644 index 00000000..60bc327c --- /dev/null +++ b/src/runtime/wamr/wamr.c @@ -0,0 +1,377 @@ +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#include "ocre_api/ocre_api.h" + +#include "ocre_api/ocre_common.h" +#include "ocre_api/ocre_timers/ocre_timer.h" + +LOG_MODULE_REGISTER(wamr_runtime, 3); + +static wasm_shared_heap_t _shared_heap = NULL; + +static void *shared_heap_buf = NULL; + +struct wamr_context { + char *buffer; + size_t size; + char error_buf[128]; + wasm_module_t module; + wasm_module_inst_t module_inst; + char **argv; + char **envp; + bool uses_ocre_api; +}; + +static int instance_execute(void *runtime_context) +{ + struct wamr_context *context = runtime_context; + wasm_module_inst_t module_inst = context->module_inst; + + // Clear any previous exceptions + wasm_runtime_clear_exception(module_inst); + + // Execute main function + const char *exception = NULL; + if (!wasm_application_execute_main(module_inst, 1, context->argv)) { + LOG_ERR("Failed to execute main function in context %p exception: %s", context, + exception ? exception : "None"); + exception = wasm_runtime_get_exception(module_inst); + if (exception) { + LOG_ERR("Container %p exception: %s", context, exception); + return -1; + } + } + + LOG_INF("Context %p completed successfully", context); + + return wasm_runtime_get_wasi_exit_code(context->module_inst); +} + +static int instance_thread_execute(void *arg) +{ + struct wamr_context *context = arg; + + wasm_runtime_init_thread_env(); + int ret = instance_execute(context); + wasm_runtime_destroy_thread_env(); + + return ret; +} + +static int runtime_init(void) +{ +#if defined(CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL) + /* Allocate memory for the shared heap */ + shared_heap_buf = user_malloc(OCRE_SHARED_HEAP_BUF_SIZE); + if (!shared_heap_buf) { + LOG_ERR("Failed to allocate memory for the shared heap of size %zu", (size_t)OCRE_SHARED_HEAP_BUF_SIZE); + return -1; + } +#elif defined(CONFIG_OCRE_SHARED_HEAP_BUF_PHYSICAL) + shared_heap_buf = OCRE_SHARED_HEAP_BUF_ADDRESS; +#endif + RuntimeInitArgs init_args; + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + init_args.mem_alloc_type = Alloc_With_Allocator; + init_args.mem_alloc_option.allocator.malloc_func = user_malloc; + init_args.mem_alloc_option.allocator.free_func = user_free; + init_args.mem_alloc_option.allocator.realloc_func = user_realloc; + // init_args.native_module_name = "env"; + // init_args.n_native_symbols = ocre_api_table_size; + // init_args.native_symbols = ocre_api_table; + + if (!wasm_runtime_full_init(&init_args)) { + LOG_ERR("Failed to initialize the WAMR runtime"); + goto error_sh_heap_buf; + } + + wasm_runtime_set_log_level(WASM_LOG_LEVEL_VERBOSE); + +#ifdef CONFIG_OCRE_SHARED_HEAP + SharedHeapInitArgs heap_init_args; + memset(&heap_init_args, 0, sizeof(heap_init_args)); + heap_init_args.pre_allocated_addr = shared_heap_buf; + heap_init_args.size = OCRE_SHARED_HEAP_BUF_SIZE; + + _shared_heap = wasm_runtime_create_shared_heap(&heap_init_args); + + if (!_shared_heap) { + LOG_ERR("Failed to create shared heap"); + goto error_runtime; + } +#endif + + if (!wasm_runtime_register_natives("env", ocre_api_table, ocre_api_table_size)) { + LOG_ERR("Failed to register the API's"); + return -1; + } + + ocre_common_init(); + ocre_timer_init(); + // TODO handle error + + return 0; + +// error_shared_heap: +error_runtime: + wasm_runtime_destroy(); + +error_sh_heap_buf: +#if defined(CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL) + free(shared_heap_buf); + shared_heap_buf = NULL; +#endif + + return -1; +} + +static int runtime_deinit(void) +{ + ocre_common_shutdown(); + + wasm_runtime_destroy(); + +#ifdef CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL + free(shared_heap_buf); +#endif + + return 0; +} + +static void *instance_create(const char *path, size_t stack_size, size_t heap_size, const char **capabilities, + const char **argv, const char **envp, const char **mounts) +{ + if (!path) { + LOG_ERR("Invalid arguments"); + return NULL; + } + + struct wamr_context *context = malloc(sizeof(struct wamr_context)); + if (!context) { + LOG_ERR("Failed to allocate memory for context size=%zu errno=%d", sizeof(struct wamr_context), errno); + return NULL; + } + + memset(context, 0, sizeof(struct wamr_context)); + + // For envp we can just keep a reference + // as the container is guaranteed to only free it after our destruction + context->envp = (char **)envp; + + int envn = 0; + while (context->envp && context->envp[envn]) { + envn++; + } + + // We need to insert argv[0]. We can keep a shallow copy, because + // the container is guaranteed to only free it after us + int argc = 0; + while (argv && argv[argc]) { + argc++; + } + + // 2 more: app name and NULL + context->argv = malloc(sizeof(char *) * (argc + 2)); + if (!context->argv) { + LOG_ERR("Failed to allocate memory for argv"); + goto error_context; + } + + memset(context->argv, 0, sizeof(char *) * (argc + 2)); + + context->argv[0] = strdup(path); + if (!context->argv[0]) { + goto error_argv; + } + + int i; + for (i = 0; i < argc; i++) { + context->argv[i + 1] = strdup(argv[i]); + if (!context->argv[i + 1]) { + goto error_argv; + } + } + + context->argv[i + 1] = NULL; + + if (context->buffer) { + LOG_WRN("Buffer already allocated. Possible memory leak!"); + } + + context->buffer = ocre_load_file(path, &context->size); + if (!context->buffer) { + LOG_ERR("Failed to load wasm program into buffer errno=%d", errno); + goto error_argv; + } + + LOG_INF("Buffer loaded successfully: %p", context->buffer); + + context->module = wasm_runtime_load((uint8_t *)context->buffer, context->size, context->error_buf, + sizeof(context->error_buf)); + if (!context->module) { + LOG_ERR("Failed to load module: %s", context->error_buf); + goto error_buffer; + } + + const char **dir_map_list = NULL; + size_t dir_map_list_len = 0; + + for (const char **cap = capabilities; cap && *cap; cap++) { + if (!strcmp(*cap, "networking")) { + const char *addr_pool[] = { + "0.0.0.0/0", + }; + + wasm_runtime_set_wasi_addr_pool(context->module, addr_pool, + sizeof(addr_pool) / sizeof(addr_pool[0])); + + const char *ns_lookup_pool[] = {"*"}; + + wasm_runtime_set_wasi_ns_lookup_pool(context->module, ns_lookup_pool, + sizeof(ns_lookup_pool) / sizeof(ns_lookup_pool[0])); + + LOG_INF("Network capability enabled"); + } else if (!strcmp(*cap, "filesystem")) { +#ifdef PICO_RP2350 + static const char *dir_map[] = {"/::/lfs/cfs"}; // TODO: fix this +#else + static const char *dir_map[] = {"/::/"}; // TODO: fix this +#endif + dir_map_list = dir_map; + dir_map_list_len = sizeof(dir_map) / sizeof(dir_map[0]); + LOG_INF("Filesystem capability enabled"); + } + } + + wasm_runtime_set_wasi_args(context->module, NULL, 0, dir_map_list, dir_map_list_len, envp, envn, context->argv, + argc + 1); + + context->module_inst = wasm_runtime_instantiate(context->module, stack_size, heap_size, context->error_buf, + sizeof(context->error_buf)); + if (!context->module_inst) { + LOG_ERR("Failed to instantiate module: %s, for context %p", context->error_buf, context); + goto error_module; + } + + for (const char **cap = capabilities; cap && *cap; cap++) { + if (!strcmp(*cap, "networking") || !strcmp(*cap, "filesystem")) { + // already set up + } else if (!strcmp(*cap, "ocre:api")) { + context->uses_ocre_api = true; + ocre_module_context_t *mod = ocre_register_module(context->module_inst); + wasm_runtime_set_custom_data(context->module_inst, mod); + } else if (!strcmp(*cap, "ocre:shared_heap")) { + if (!wasm_runtime_attach_shared_heap(context->module_inst, _shared_heap)) { + LOG_ERR("Failed to attach shared heap"); + goto error_instance; + } + LOG_INF("Shared heap capability enabled"); + } else { + LOG_WRN("Capability '%s' not supported by runtime", *cap); + } + } + + return context; + +error_instance: + wasm_runtime_deinstantiate(context->module_inst); + +error_module: + wasm_runtime_unload(context->module); + +error_buffer: + ocre_unload_file(context->buffer, context->size); + context->buffer = NULL; + +error_argv: + // only free what we allocated + free(context->argv[0]); + free(context->argv); + +error_context: + free(context); + + return NULL; +} + +static int instance_kill(void *runtime_context) +{ + struct wamr_context *context = runtime_context; + + if (!context) { + return -1; + } + + wasm_runtime_terminate(context->module_inst); + + return 0; +} + +static int instance_pause(void *runtime_context) +{ + struct wamr_context *context = runtime_context; + + if (!context) { + return -1; + } + + return -1; + // wasm_runtime_terminate(context->module_inst); + + return 0; +} + +static int instance_destroy(void *runtime_context) +{ + struct wamr_context *context = runtime_context; + + if (!context) { + return -1; + } + + ocre_unregister_module(context->module_inst); + + wasm_runtime_deinstantiate(context->module_inst); + context->module_inst = NULL; + + wasm_runtime_unload(context->module); + + if (ocre_unload_file(context->buffer, context->size)) { + LOG_ERR("Failed to unload file"); + } + context->buffer = NULL; + + free(context->argv[0]); + free(context->argv); + + free(context); + + return 0; +} + +const struct ocre_runtime_vtable wamr_vtable = { + .runtime_name = "wamr", + .init = runtime_init, + .deinit = runtime_deinit, + .create = instance_create, + .destroy = instance_destroy, + .thread_execute = instance_thread_execute, + .kill = instance_kill, + .pause = instance_pause, + // .unpause = instance_unpause, +}; diff --git a/src/samples-mini/posix/main.c b/src/samples-mini/posix/main.c deleted file mode 100644 index 67c781d2..00000000 --- a/src/samples-mini/posix/main.c +++ /dev/null @@ -1,114 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ocre_core_external.h" -#include -#include - -#ifdef HAS_GENERATED_INPUT -#include -#else -#include -#endif - -void create_sample_container(); - -int main(int argc, char *argv[]) { - ocre_cs_ctx ctx; - ocre_container_init_arguments_t args; - char *container_filename = "hello"; - - ocre_app_storage_init(); - - // Step 1: Initialize the Ocre runtime - ocre_container_runtime_status_t ret = ocre_container_runtime_init(&ctx, &args); - - if (ret == RUNTIME_STATUS_INITIALIZED) { - printf("\n\nOcre runtime started\n"); - - if (argc > 1) { - set_argc(argc); - container_filename = argv[1]; // Use the filename as the container name/sha256 - } - else { - create_sample_container(container_filename); - } - - // Step 2: Create the container, this allocates and loads the container binary - ocre_container_data_t ocre_container_data[CONFIG_MAX_CONTAINERS]; - int container_ID[CONFIG_MAX_CONTAINERS]; - ocre_container_runtime_cb callback[CONFIG_MAX_CONTAINERS]; - - int i = 0; - do { - ocre_container_data[i].heap_size = 0; - snprintf(ocre_container_data[i].name, sizeof(ocre_container_data[i].name), "Container%d", i); - snprintf(ocre_container_data[i].sha256, sizeof(ocre_container_data[i].sha256), "%s", container_filename); - ocre_container_data[i].timers = 0; - ocre_container_data[i].watchdog_interval = 0; - ocre_container_runtime_create_container(&ctx, &ocre_container_data[i], &container_ID[i], callback[i]); - - // Step 3: Execute the container - ocre_container_runtime_run_container(container_ID[i], callback[i]); - core_sleep_ms(1000); - - i++; - container_filename = argv[i+1]; - } while (i < argc - 1); - - // Loop forever, without this the application will exit and stop all execution - while (true) { - core_sleep_ms(1000); - } - - } else { - printf("\n\nOcre runtime failed to start.\n"); - } -} - -/** - * Creates a container image file using the sample "hello-word" WASM module - * This is for demostration purposes only and does not perform any error checking. - * - * @param file_name a string containing the name of the file to create - */ - -void create_sample_container(char *file_name) { - static char file_path[64]; - snprintf(file_path, sizeof(file_path), "./%s/%s.bin", APP_RESOURCE_PATH, file_name); - - // Create directories if they don't exist - mkdir("./ocre", 0755); - mkdir("./ocre/images", 0755); - - // Open the file for writing - int fd = open(file_path, O_CREAT | O_RDWR, 0644); - if (fd == -1) { - perror("Error opening file"); - return; - } - // Write the binary data to the file - ssize_t bytes_written = write(fd, wasm_binary, wasm_binary_len); - if (bytes_written == -1) { - perror("Error writing to file"); - } else { - printf("Wrote %zd bytes to %s\n", bytes_written, file_path); - } - - // Close the file - close(fd); -} diff --git a/src/samples/bash_runtime/posix/CMakeLists.txt b/src/samples/bash_runtime/posix/CMakeLists.txt new file mode 100644 index 00000000..7b014703 --- /dev/null +++ b/src/samples/bash_runtime/posix/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 3.20.0) + +project (ocre_sample_bash_runtime) + +add_subdirectory(bash) + +add_executable(ocre_bash + main.c +) + +target_link_libraries(ocre_bash + PUBLIC + OcreCore + OcreRuntime + OcreRuntimeBash +) + +target_link_libraries(ocre_bash + PRIVATE + -lpthread +) diff --git a/src/samples/bash_runtime/posix/bash/CMakeLists.txt b/src/samples/bash_runtime/posix/bash/CMakeLists.txt new file mode 100644 index 00000000..67abe87a --- /dev/null +++ b/src/samples/bash_runtime/posix/bash/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.20.0) + +set(OCRE_DEFAULT_WORKING_DIRECTORY "/var/lib/ocre") + +add_library(OcreRuntimeBash) + +target_sources(OcreRuntimeBash PRIVATE + bash.c +) + +target_include_directories(OcreRuntimeBash PUBLIC + include +) + +target_link_libraries(OcreRuntimeBash PUBLIC + OcrePlatform + OcreRuntime +) diff --git a/src/samples/bash_runtime/posix/bash/bash.c b/src/samples/bash_runtime/posix/bash/bash.c new file mode 100644 index 00000000..2c49908f --- /dev/null +++ b/src/samples/bash_runtime/posix/bash/bash.c @@ -0,0 +1,182 @@ +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include + +LOG_MODULE_REGISTER(bash_runtime); + +struct bash_context { + pid_t pid; + char **argv; + char **envp; +}; + +static int instance_execute(void *runtime_context) +{ + struct bash_context *context = runtime_context; + + // TODO: configure fileactions and attr + + int ret; + ret = posix_spawnp(&context->pid, "/bin/bash", NULL, NULL, context->argv, context->envp); + + if (ret) { + LOG_ERR("Failed to spawn process ret=%d errno=%d", ret, errno); + return -1; + } + + LOG_INF("Process spawned successfully PID=%d", context->pid); + + int status; + + pid_t pid = waitpid(context->pid, &status, 0); + if (pid == -1) { + LOG_ERR("Failed to wait for process"); + return -1; + } + + LOG_INF("Waitpid returned %d status: %d", pid, WEXITSTATUS(status)); + + LOG_INF("Container %p completed successfully", context); + + return WEXITSTATUS(status); +} + +static int instance_thread_execute(void *arg) +{ + struct bash_context *context = arg; + + int ret = instance_execute(context); + + return ret; +} + +static void *instance_create(const char *path, size_t stack_size, size_t heap_size, const char **capabilities, + const char **argv, const char **envp, const char **mounts) +{ + if (!path) { + LOG_ERR("Invalid arguments"); + return NULL; + } + + struct bash_context *context = malloc(sizeof(struct bash_context)); + if (!context) { + LOG_ERR("Failed to allocate memory for BASH container size=%zu errno=%d", sizeof(struct bash_context), + errno); + return NULL; + } + + memset(context, 0, sizeof(struct bash_context)); + + for (const char **cap = capabilities; cap && *cap; cap++) { + LOG_WRN("Capability '%s' not supported by runtime", *cap); + } + + // For envp we can just keep a reference + // as the container is guaranteed to only free it after our lifetime + context->envp = (char **)envp; + + // We need to insert argv[0] and argv[1]. We can keep a shallow copy, because + // the container is guaranteed to only free it after our lifetime + int argc = 0; + while (argv && argv[argc]) { + argc++; + } + + // 3 more: bash, script name and NULL + context->argv = malloc(sizeof(char *) * (argc + 3)); + if (!context->argv) { + LOG_ERR("Failed to allocate memory for argv"); + goto error_context; + } + + memset(context->argv, 0, sizeof(char *) * (argc + 3)); + + context->argv[0] = strdup("/bin/bash"); + if (!context->argv[0]) { + goto error_argv; + } + + context->argv[1] = strdup(path); + if (!context->argv[1]) { + goto error_argv; + } + + int i; + for (i = 0; i < argc; i++) { + context->argv[i + 2] = strdup(argv[i]); + if (!context->argv[i + 2]) { + goto error_argv; + } + } + + context->argv[i + 2] = NULL; + + return context; + + // TODO: set up chroot, namespace, jails, whatever + // configure fileactions here instead? + +error_argv: + free(context->argv[0]); + free(context->argv[1]); + free(context->argv); + +error_context: + free(context); + + return NULL; +} + +static int instance_kill(void *runtime_context) +{ + struct bash_context *context = runtime_context; + + if (!context) { + return -1; + } + + int rc = kill(context->pid, SIGKILL); + if (rc < 0) { + LOG_ERR("Failed to kill process: rc=%d, errno=%d", rc, errno); + return -1; + } + + return 0; +} + +static int instance_destroy(void *runtime_context) +{ + struct bash_context *context = runtime_context; + + if (!context) { + return -1; + } + + free(context->argv[0]); + free(context->argv[1]); + free(context->argv); + + free(context); + + return 0; +} + +const struct ocre_runtime_vtable bash_vtable = { + .runtime_name = "bash", + .create = instance_create, + .destroy = instance_destroy, + .thread_execute = instance_thread_execute, + .kill = instance_kill, +}; diff --git a/src/samples/bash_runtime/posix/bash/include/ocre/runtime/bash/bash.h b/src/samples/bash_runtime/posix/bash/include/ocre/runtime/bash/bash.h new file mode 100644 index 00000000..f2400918 --- /dev/null +++ b/src/samples/bash_runtime/posix/bash/include/ocre/runtime/bash/bash.h @@ -0,0 +1,8 @@ +#ifndef OCRE_RUNTIME_BASH_H +#define OCRE_RUNTIME_BASH_H + +#include + +extern const struct ocre_runtime_vtable bash_vtable; + +#endif /* OCRE_RUNTIME_BASH_H */ diff --git a/src/samples/bash_runtime/posix/main.c b/src/samples/bash_runtime/posix/main.c new file mode 100644 index 00000000..86a08e61 --- /dev/null +++ b/src/samples/bash_runtime/posix/main.c @@ -0,0 +1,87 @@ +#include +#include + +#include + +#include +#include + +#include "../../ocre/container.h" + +#define OCRE_DEFAULT_WORKING_DIRECTORY "./var/lib/ocre" + +int main(int argc, char *argv[]) +{ + int rc; + + rc = ocre_initialize(); + if (rc) { + fprintf(stderr, "Failed to initialize OCRE\n"); + return 1; + } + + rc = ocre_initialize_with_runtimes((const struct ocre_runtime_vtable *const[]){&bash_vtable, NULL}); + if (rc) { + fprintf(stderr, "Failed to initialize runtimes\n"); + return 1; + } + + struct ocre_context *ocre = ocre_create_context(OCRE_DEFAULT_WORKING_DIRECTORY); + if (!ocre) { + fprintf(stderr, "Failed to create ocre context\n"); + return 1; + } + + struct ocre_container_args args = { + .argv = (const char *[]){"teste", "dois", NULL}, + .envp = (const char *[]){"VAR=variable", "VAR2=variable2", NULL}, + }; + + struct ocre_container *wasm_container = + ocre_context_create_container(ocre, "blinky", "wamr", NULL, false, &args); + if (!wasm_container) { + fprintf(stderr, "Failed to create WASM container\n"); + return 1; + } + + struct ocre_container *bash_container = + ocre_context_create_container(ocre, "atym.sh", "bash", "my_bash", true, &args); + if (!bash_container) { + fprintf(stderr, "Failed to create bash container\n"); + return 1; + } + + fprintf(stderr, "Will start WAMR container\n"); + + rc = ocre_container_start(wasm_container); + if (rc) { + fprintf(stderr, "Failed to start WASM container\n"); + return 1; + } + + fprintf(stderr, "Will start bash container\n"); + + rc = ocre_container_start(bash_container); + if (rc) { + fprintf(stderr, "Failed to start bash container\n"); + return 1; + } + + int exit_code; + + if (ocre_container_wait(bash_container, &exit_code)) { + fprintf(stderr, "Failed to wait for bash container\n"); + return 1; + } + + fprintf(stderr, "Bash container exited with status %d\n", exit_code); + + if (ocre_container_wait(wasm_container, &exit_code)) { + fprintf(stderr, "Failed to wait for WASM container\n"); + return 1; + } + + fprintf(stderr, "WASM container exited with status %d\n", exit_code); + + return 0; +} diff --git a/src/samples/demo/main.c b/src/samples/demo/main.c new file mode 100644 index 00000000..d6296ff0 --- /dev/null +++ b/src/samples/demo/main.c @@ -0,0 +1,147 @@ +#include +#include + +#include + +const struct ocre_container_args args = { + .capabilities = (const char *[]){"ocre:api", NULL}, +}; + +int main(int argc, char *argv[]) +{ + int rc; + + rc = ocre_initialize(); + if (rc) { + fprintf(stderr, "Failed to initialize runtimes\n"); + return 1; + } + + struct ocre_context *ocre = ocre_create_context(NULL); + if (!ocre) { + fprintf(stderr, "Failed to create ocre context\n"); + return 1; + } + + struct ocre_container *hello_world = + ocre_context_create_container(ocre, "hello-world.wasm", "wamr", NULL, false, &args); + + if (!hello_world) { + fprintf(stderr, "Failed to create container\n"); + return 1; + } + + rc = ocre_container_start(hello_world); + if (rc) { + fprintf(stderr, "Failed to start container\n"); + return 1; + } + + rc = ocre_context_remove_container(ocre, hello_world); + if (rc) { + fprintf(stderr, "Failed to remove container\n"); + return 1; + } + + struct ocre_container *blinky = ocre_context_create_container(ocre, "blinky.wasm", "wamr", NULL, true, &args); + + if (!blinky) { + fprintf(stderr, "Failed to create container\n"); + return 1; + } + + rc = ocre_container_start(blinky); + if (rc) { + fprintf(stderr, "Failed to start container\n"); + return 1; + } + + sleep(2); + + rc = ocre_container_kill(blinky); + if (rc) { + fprintf(stderr, "Failed to kill container\n"); + return 1; + } + + int status; + rc = ocre_container_wait(blinky, &status); + if (rc) { + fprintf(stderr, "Failed to wait for container\n"); + return 1; + } + + fprintf(stderr, "Container exited with status %d\n", status); + + // rc = ocre_context_remove_container(ocre, blinky); + // if (rc) { + // fprintf(stderr, "Failed to remove container\n"); + // return 1; + // } + + // struct ocre_container *subscriber = + // ocre_context_create_container(ocre, "subscriber.wasm", "wamr", NULL, true, &args); + + // if (!subscriber) { + // fprintf(stderr, "Failed to create container\n"); + // return 1; + // } + + // struct ocre_container *publisher = + // ocre_context_create_container(ocre, "publisher.wasm", "wamr", NULL, true, &args); + + // if (!publisher) { + // fprintf(stderr, "Failed to create container\n"); + // return 1; + // } + + // rc = ocre_container_start(subscriber); + // if (rc) { + // fprintf(stderr, "Failed to start container\n"); + // return 1; + // } + + // sleep(5); + + // rc = ocre_container_start(publisher); + // if (rc) { + // fprintf(stderr, "Failed to start container\n"); + // return 1; + // } + + // sleep(10); + + // rc = ocre_container_kill(subscriber); + // if (rc) { + // fprintf(stderr, "Failed to kill container\n"); + // return 1; + // } + + // rc = ocre_container_kill(publisher); + // if (rc) { + // fprintf(stderr, "Failed to kill container\n"); + // return 1; + // } + + // rc = ocre_container_wait(subscriber, &status); + // if (rc) { + // fprintf(stderr, "Failed to wait for container\n"); + // return 1; + // } + + // fprintf(stderr, "Container exited with status %d\n", status); + + // rc = ocre_container_wait(publisher, &status); + // if (rc) { + // fprintf(stderr, "Failed to wait for container\n"); + // return 1; + // } + + // fprintf(stderr, "Container exited with status %d\n", status); + + // ocre_destroy_context(ocre); + + // ocre_deinitialize(); + + return 0; +} diff --git a/src/samples/demo/posix/CMakeLists.txt b/src/samples/demo/posix/CMakeLists.txt new file mode 100644 index 00000000..fd03e014 --- /dev/null +++ b/src/samples/demo/posix/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.20.0) + +set(OCRE_DEFAULT_WORKING_DIRECTORY "/var/lib/ocre") + +project (ocre_sample_demo) + +add_executable(ocre_demo + ../main.c +) + +target_link_libraries(ocre_demo + PUBLIC + OcreCore +) + +target_link_libraries(ocre_demo + PRIVATE + -lpthread +) diff --git a/src/samples/demo/zephyr/CMakeLists.txt b/src/samples/demo/zephyr/CMakeLists.txt new file mode 100644 index 00000000..507015f8 --- /dev/null +++ b/src/samples/demo/zephyr/CMakeLists.txt @@ -0,0 +1,21 @@ +# This file is to be used to build a zephyr firmware including the ocre demo +# automatically uses the ocre module in the parent directory + +cmake_minimum_required(VERSION 3.20.0) + +# comment out to use the ocre module provided by Zephyr +list(APPEND ZEPHYR_EXTRA_MODULES ${CMAKE_CURRENT_LIST_DIR}/../../../..) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project (ocre_sample_mini) + +target_sources(app + PRIVATE + ../main.c +) + +target_link_libraries(app + PUBLIC + OcreCore +) diff --git a/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33_w.conf b/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33_w.conf new file mode 100644 index 00000000..fd303152 --- /dev/null +++ b/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33_w.conf @@ -0,0 +1,2 @@ +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_SHARED_MULTI_HEAP=y diff --git a/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay b/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay new file mode 100644 index 00000000..58910875 --- /dev/null +++ b/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay @@ -0,0 +1,29 @@ +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + user_data_partition: storage_partition: partition@600000 { + label = "storage"; + reg = <0x410000 0x800000>; + }; + }; +}; + +/ { + fstab { + compatible = "zephyr,fstab"; + lfs1: lfs1 { + compatible = "zephyr,fstab,littlefs"; + read-size = <256>; + prog-size = <256>; + cache-size = <256>; + lookahead-size = <256>; + block-cycles = <512>; + partition = <&user_data_partition>; + mount-point = "/lfs"; + automount; + }; + }; +}; diff --git a/src/samples/demo/zephyr/prj.conf b/src/samples/demo/zephyr/prj.conf new file mode 100644 index 00000000..74a2b4ec --- /dev/null +++ b/src/samples/demo/zephyr/prj.conf @@ -0,0 +1,22 @@ +#Logging +CONFIG_LOG=y +CONFIG_LOG_MODE_MINIMAL=y + +# Filesystem +CONFIG_ZVFS_POLL_MAX=10 +CONFIG_ZVFS_OPEN_MAX=10 + +# Memory optopns +CONFIG_DYNAMIC_THREAD_STACK_SIZE=8192 +CONFIG_MAIN_STACK_SIZE=8192 +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=-1 + +# Ocre configuration +CONFIG_OCRE=y +CONFIG_OCRE_TIMER=y +CONFIG_OCRE_CONTAINER_MESSAGING=y +CONFIG_OCRE_MERGE_HEX=y +CONFIG_OCRE_WAMR_AOT=y +CONFIG_OCRE_SHARED_HEAP=y +#CONFIG_OCRE_GPIO=y +#CONFIG_OCRE_SENSORS=y diff --git a/src/samples/mini/main.c b/src/samples/mini/main.c new file mode 100644 index 00000000..b129ad36 --- /dev/null +++ b/src/samples/mini/main.c @@ -0,0 +1,47 @@ +#include +#include + +#include + +int main(int argc, char *argv[]) +{ + int rc; + + rc = ocre_initialize(); + if (rc) { + fprintf(stderr, "Failed to initialize runtimes\n"); + return 1; + } + + struct ocre_context *ocre = ocre_create_context(NULL); + if (!ocre) { + fprintf(stderr, "Failed to create ocre context\n"); + return 1; + } + + struct ocre_container *container = + ocre_context_create_container(ocre, "hello-world.wasm", "wamr", NULL, false, NULL); + + if (!container) { + fprintf(stderr, "Failed to create container\n"); + return 1; + } + + rc = ocre_container_start(container); + if (rc) { + fprintf(stderr, "Failed to start container\n"); + return 1; + } + + rc = ocre_context_remove_container(ocre, container); + if (rc) { + fprintf(stderr, "Failed to remove container\n"); + return 1; + } + + ocre_destroy_context(ocre); + + ocre_deinitialize(); + + return 0; +} diff --git a/src/samples/mini/posix/CMakeLists.txt b/src/samples/mini/posix/CMakeLists.txt new file mode 100644 index 00000000..c8fc45ea --- /dev/null +++ b/src/samples/mini/posix/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.20.0) + +set(OCRE_DEFAULT_WORKING_DIRECTORY "/var/lib/ocre") + +project (ocre_sample_mini) + +add_executable(ocre_mini + ../main.c +) + +target_link_libraries(ocre_mini + PUBLIC + OcreCore +) + +target_link_libraries(ocre_mini + PRIVATE + -lpthread +) diff --git a/src/samples/mini/zephyr/CMakeLists.txt b/src/samples/mini/zephyr/CMakeLists.txt new file mode 100644 index 00000000..507015f8 --- /dev/null +++ b/src/samples/mini/zephyr/CMakeLists.txt @@ -0,0 +1,21 @@ +# This file is to be used to build a zephyr firmware including the ocre demo +# automatically uses the ocre module in the parent directory + +cmake_minimum_required(VERSION 3.20.0) + +# comment out to use the ocre module provided by Zephyr +list(APPEND ZEPHYR_EXTRA_MODULES ${CMAKE_CURRENT_LIST_DIR}/../../../..) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project (ocre_sample_mini) + +target_sources(app + PRIVATE + ../main.c +) + +target_link_libraries(app + PUBLIC + OcreCore +) diff --git a/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33_w.conf b/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33_w.conf new file mode 100644 index 00000000..eebef5c9 --- /dev/null +++ b/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33_w.conf @@ -0,0 +1,2 @@ +CONFIG_TEST_RANDOM_GENERATOR=y +#CONFIG_SHARED_MULTI_HEAP=y diff --git a/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay b/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay new file mode 100644 index 00000000..58910875 --- /dev/null +++ b/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay @@ -0,0 +1,29 @@ +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + user_data_partition: storage_partition: partition@600000 { + label = "storage"; + reg = <0x410000 0x800000>; + }; + }; +}; + +/ { + fstab { + compatible = "zephyr,fstab"; + lfs1: lfs1 { + compatible = "zephyr,fstab,littlefs"; + read-size = <256>; + prog-size = <256>; + cache-size = <256>; + lookahead-size = <256>; + block-cycles = <512>; + partition = <&user_data_partition>; + mount-point = "/lfs"; + automount; + }; + }; +}; diff --git a/src/samples/mini/zephyr/prj.conf b/src/samples/mini/zephyr/prj.conf new file mode 100644 index 00000000..5f06db51 --- /dev/null +++ b/src/samples/mini/zephyr/prj.conf @@ -0,0 +1,15 @@ +#Logging +CONFIG_LOG=y +CONFIG_LOG_MODE_MINIMAL=y + +# Filesystem +CONFIG_ZVFS_POLL_MAX=10 +CONFIG_ZVFS_OPEN_MAX=10 + +# Memory optopns +CONFIG_DYNAMIC_THREAD_STACK_SIZE=8192 +CONFIG_MAIN_STACK_SIZE=8192 +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=-1 + +# Ocre configuration +CONFIG_OCRE=y diff --git a/src/samples/readline/posix/CMakeLists.txt b/src/samples/readline/posix/CMakeLists.txt new file mode 100644 index 00000000..076ae100 --- /dev/null +++ b/src/samples/readline/posix/CMakeLists.txt @@ -0,0 +1,38 @@ +cmake_minimum_required(VERSION 3.20.0) + +project (ocre_sample_supervisor) + +add_executable(ocred + ocred.c +) + +target_link_libraries(ocred + PUBLIC + OcreCore +) + +target_link_libraries(ocred + PRIVATE + -lpthread +) + +add_executable(ocre + ocre.c +) + +target_link_libraries(ocre + PUBLIC + OcreCore # just link for now, to validate the build + OcreShell +) + +target_link_libraries(OcreShell + PUBLIC + OcreCore +) + + +target_link_libraries(ocre + PRIVATE + -lpthread +) diff --git a/src/samples/readline/posix/ocre.c b/src/samples/readline/posix/ocre.c new file mode 100644 index 00000000..c40bf457 --- /dev/null +++ b/src/samples/readline/posix/ocre.c @@ -0,0 +1,56 @@ +#include +#include +#include + +#include + +#include // remove + +// keep a reference to the single instance of the runtime +struct ocre_context *ocre_global_context = NULL; + +int main(int argc, char *argv[]) +{ + // Initialize OCRE + if (ocre_initialize() != 0) { + return -1; + } + + fprintf(stderr, "Initialized Ocre\n"); + + // Create a context + ocre_global_context = ocre_create_context("var/lib/ocre"); + if (!ocre_global_context) { + fprintf(stderr, "Failed to create Ocre context\n"); + ocre_deinitialize(); + return -1; + } + + fprintf(stderr, "Created Ocre context: %p\n", ocre_global_context); + + struct ocre_container *hello = + ocre_context_create_container(ocre_global_context, "hello-world.wasm", "wamr", "marco", true, NULL); + + if (!hello) { + fprintf(stderr, "Failed to create container\n"); + return 1; + } + + struct ocre_container *subscriber = + ocre_context_create_container(ocre_global_context, "subscriber.wasm", "wamr", NULL, true, NULL); + + if (!subscriber) { + fprintf(stderr, "Failed to create container\n"); + return 1; + } + + struct ocre_container *publisher = + ocre_context_create_container(ocre_global_context, "publisher.wasm", "wamr", NULL, true, NULL); + + if (!publisher) { + fprintf(stderr, "Failed to create container\n"); + return 1; + } + + return ocre_shell(ocre_global_context, argc, argv); +} diff --git a/src/samples/supervisor/zephyr/CMakeLists.txt b/src/samples/supervisor/zephyr/CMakeLists.txt new file mode 100644 index 00000000..b1d647ee --- /dev/null +++ b/src/samples/supervisor/zephyr/CMakeLists.txt @@ -0,0 +1,29 @@ +# This file is to be used to build a zephyr firmware including the ocre demo +# automatically uses the ocre module in the parent directory + +cmake_minimum_required(VERSION 3.20.0) + +# comment out to use the ocre module provided by zephyr +list(APPEND ZEPHYR_EXTRA_MODULES ${CMAKE_CURRENT_LIST_DIR}/../../../..) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project (ocre_sample_supervisor) + +target_sources(app + PRIVATE + service.c + shell.c +) + +target_link_libraries(app + PUBLIC + OcreCore + OcreShell +) + +target_link_libraries(OcreShell + PUBLIC + zephyr_interface + OcreCore +) diff --git a/src/samples/supervisor/zephyr/boards/b_u585i_iot02a.conf b/src/samples/supervisor/zephyr/boards/b_u585i_iot02a.conf new file mode 100644 index 00000000..4709e32e --- /dev/null +++ b/src/samples/supervisor/zephyr/boards/b_u585i_iot02a.conf @@ -0,0 +1,2 @@ +CONFIG_STM32_MEMMAP=y +CONFIG_OCRE_MERGE_HEX=y diff --git a/boards/b_u585i_iot02a.overlay b/src/samples/supervisor/zephyr/boards/b_u585i_iot02a.overlay similarity index 86% rename from boards/b_u585i_iot02a.overlay rename to src/samples/supervisor/zephyr/boards/b_u585i_iot02a.overlay index 1419cd47..7f2a0d0c 100644 --- a/boards/b_u585i_iot02a.overlay +++ b/src/samples/supervisor/zephyr/boards/b_u585i_iot02a.overlay @@ -109,7 +109,8 @@ }; // 64MB external flash -&mx25lm51245 { +&mx25lm51245 { // -el "/usr/local/STMicroelectronics/STM32Cube/STM32CubeProgrammer/bin/ExternalLoader/MX25LM51245G_STM32U585I-IOT02A.stldr" + reg = <0x70000000 DT_SIZE_M(64)>; partitions { /delete-node/ partition; @@ -121,6 +122,23 @@ }; }; +/ { + fstab { + compatible = "zephyr,fstab"; + lfs1: lfs1 { + compatible = "zephyr,fstab,littlefs"; + read-size = <256>; + prog-size = <256>; + cache-size = <256>; + lookahead-size = <256>; + block-cycles = <512>; + partition = <&user_data_partition>; + mount-point = "/lfs"; + automount; + }; + }; +}; + &die_temp { status = "disabled"; }; diff --git a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.conf b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.conf new file mode 100644 index 00000000..b8692911 --- /dev/null +++ b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.conf @@ -0,0 +1,6 @@ +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_SHARED_MULTI_HEAP=y + +# for led +CONFIG_NETWORKING=y +CONFIG_WIFI=y diff --git a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay new file mode 100644 index 00000000..58910875 --- /dev/null +++ b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay @@ -0,0 +1,29 @@ +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + user_data_partition: storage_partition: partition@600000 { + label = "storage"; + reg = <0x410000 0x800000>; + }; + }; +}; + +/ { + fstab { + compatible = "zephyr,fstab"; + lfs1: lfs1 { + compatible = "zephyr,fstab,littlefs"; + read-size = <256>; + prog-size = <256>; + cache-size = <256>; + lookahead-size = <256>; + block-cycles = <512>; + partition = <&user_data_partition>; + mount-point = "/lfs"; + automount; + }; + }; +}; diff --git a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w_mcuboot.conf b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w_mcuboot.conf new file mode 100644 index 00000000..9799284a --- /dev/null +++ b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w_mcuboot.conf @@ -0,0 +1,6 @@ +CONFIG_TEST_RANDOM_GENERATOR=y + +# for led +CONFIG_NETWORKING=y +CONFIG_WIFI=y +CONFIG_MAIN_STACK_SIZE=2048 diff --git a/src/samples/supervisor/zephyr/prj.conf b/src/samples/supervisor/zephyr/prj.conf new file mode 100644 index 00000000..3ef6c14b --- /dev/null +++ b/src/samples/supervisor/zephyr/prj.conf @@ -0,0 +1,48 @@ +CONFIG_SHELL=y +CONFIG_BOOT_BANNER=y +CONFIG_SHELL_PROMPT_UART="ocre:~$ " +CONFIG_NET_SHELL=y +CONFIG_NET_L2_WIFI_SHELL=n +CONFIG_FILE_SYSTEM_SHELL=y + +CONFIG_LOG=y + +# Networking options +CONFIG_NET_IPV4=y +CONFIG_NET_IPV6=y +CONFIG_NET_UDP=y +CONFIG_NET_SOCKETS=y + +CONFIG_NET_TX_STACK_SIZE=2048 +CONFIG_NET_BUF_TX_COUNT=16 +CONFIG_NET_RX_STACK_SIZE=4096 +CONFIG_NET_BUF_RX_COUNT=32 +CONFIG_NET_MGMT_EVENT_STACK_SIZE=2048 + +# file descriptors +CONFIG_ZVFS_POLL_MAX=5 +CONFIG_ZVFS_OPEN_MAX=8 + +CONFIG_NET_DHCPV4=y + +# Memory optopns +CONFIG_DYNAMIC_THREAD_STACK_SIZE=8192 +CONFIG_MAIN_STACK_SIZE=8192 +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=-1 +CONFIG_SHELL_STACK_SIZE=8192 + +CONFIG_MAX_PTHREAD_MUTEX_COUNT=32 +CONFIG_POSIX_THREAD_THREADS_MAX=10 + +# Ocre configuration +CONFIG_OCRE=y +CONFIG_OCRE_SHELL=y +CONFIG_OCRE_TIMER=y +CONFIG_OCRE_CONTAINER_MESSAGING=y +#CONFIG_SENSOR=y +#CONFIG_RNG_SENSOR=y + +CONFIG_SHELL_GETOPT=y + +CONFIG_DEBUG=y +CONFIG_LOG_MODE_IMMEDIATE=y diff --git a/src/samples/supervisor/zephyr/service.c b/src/samples/supervisor/zephyr/service.c new file mode 100644 index 00000000..eb2b7705 --- /dev/null +++ b/src/samples/supervisor/zephyr/service.c @@ -0,0 +1,27 @@ +#include +#include + +// keep a reference to the single instance of the runtime +struct ocre_context *ocre_global_context = NULL; + +int main(int argc, char *argv[]) +{ + // Initialize OCRE + if (ocre_initialize() != 0) { + return -1; + } + + fprintf(stderr, "Initialized Ocre\n"); + + // Create a context + ocre_global_context = ocre_create_context("/lfs/ocre"); + if (!ocre_global_context) { + fprintf(stderr, "Failed to create Ocre context\n"); + ocre_deinitialize(); + return -1; + } + + fprintf(stderr, "Created Ocre context: %p\n", ocre_global_context); + + return 0; +} diff --git a/src/samples/supervisor/zephyr/shell.c b/src/samples/supervisor/zephyr/shell.c new file mode 100644 index 00000000..5ac0686d --- /dev/null +++ b/src/samples/supervisor/zephyr/shell.c @@ -0,0 +1,22 @@ +#include +#include + +#include + +#include +#include + +extern struct ocre_context *ocre_global_context; + +static int cmd_ocre_shell(const struct shell *sh, size_t argc, char **argv) +{ + // getopt_init(); + + // volatile struct getopt_state *state = getopt_state_get(); + + // optreset = 1; + + return ocre_shell(ocre_global_context, argc, argv); +} + +SHELL_CMD_REGISTER(ocre, NULL, "OCRE management", cmd_ocre_shell); diff --git a/src/shared/platform/posix/core_eventq.c b/src/shared/platform/posix/core_eventq.c deleted file mode 100644 index 1146a371..00000000 --- a/src/shared/platform/posix/core_eventq.c +++ /dev/null @@ -1,74 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "ocre_core_external.h" -#include -#include - -int core_eventq_init(core_eventq_t *eventq, size_t item_size, size_t max_items) { - eventq->buffer = core_malloc(item_size * max_items); - if (!eventq->buffer) { - return -ENOMEM; - } - eventq->item_size = item_size; - eventq->max_items = max_items; - eventq->count = 0; - eventq->head = 0; - eventq->tail = 0; - pthread_mutex_init(&eventq->mutex, NULL); - pthread_cond_init(&eventq->cond, NULL); - return 0; -} - -int core_eventq_peek(core_eventq_t *eventq, void *event) { - pthread_mutex_lock(&eventq->mutex); - if (eventq->count == 0) { - pthread_mutex_unlock(&eventq->mutex); - return -ENOMSG; - } - memcpy(event, (char *)eventq->buffer + (eventq->head * eventq->item_size), eventq->item_size); - pthread_mutex_unlock(&eventq->mutex); - return 0; -} - -int core_eventq_get(core_eventq_t *eventq, void *event) { - pthread_mutex_lock(&eventq->mutex); - if (eventq->count == 0) { - pthread_mutex_unlock(&eventq->mutex); - return -ENOENT; - } - memcpy(event, (char *)eventq->buffer + (eventq->head * eventq->item_size), eventq->item_size); - eventq->head = (eventq->head + 1) % eventq->max_items; - eventq->count--; - pthread_mutex_unlock(&eventq->mutex); - return 0; -} - -int core_eventq_put(core_eventq_t *eventq, const void *event) { - pthread_mutex_lock(&eventq->mutex); - if (eventq->count >= eventq->max_items) { - pthread_mutex_unlock(&eventq->mutex); - return -ENOMEM; - } - memcpy((char *)eventq->buffer + (eventq->tail * eventq->item_size), event, eventq->item_size); - eventq->tail = (eventq->tail + 1) % eventq->max_items; - eventq->count++; - pthread_cond_signal(&eventq->cond); - pthread_mutex_unlock(&eventq->mutex); - return 0; -} - -void core_eventq_destroy(core_eventq_t *eventq) { - pthread_mutex_destroy(&eventq->mutex); - pthread_cond_destroy(&eventq->cond); - if (eventq->buffer) { - core_free(eventq->buffer); - eventq->buffer = NULL; - } -} - - diff --git a/src/shared/platform/posix/core_fs.c b/src/shared/platform/posix/core_fs.c deleted file mode 100644 index fc559b14..00000000 --- a/src/shared/platform/posix/core_fs.c +++ /dev/null @@ -1,160 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ocre_core_external.h" - -#define MAX_PATH_LEN 256 - -/* -When containers are passed locally, from the filesystem - we don't need to construct the path. -Instead, we just use the original file's location. This is indicated whether the container was passed as a buffer, -or as a program parameter. Encapsulation is used to avoid global variables. -*/ -static int stored_argc = 0; - -void set_argc(int argc) { - stored_argc = argc; -} - - -/** - * @brief Retrieves the stored argc value. - * - * Returns the argc value previously set by set_argc(). - * Useful for conditional logic based on argument count. - * - * @return The stored argc value. - */ -static int get_argc() { - return stored_argc; -} - - -int core_construct_filepath(char *path, size_t len, char *name) { - char cwd[PATH_MAX]; - if (getcwd(cwd, sizeof(cwd)) != NULL) { - // Shall be in /build folder - LOG_DBG("Current working dir: %s", cwd); - } - if (get_argc() > 1) { - strcpy(path, name); - return 0; - } else { - return snprintf(path, len, "%s/%s/%s.bin", cwd, APP_RESOURCE_PATH, name); - } -} - - -int core_filestat(const char *path, size_t *size) { - struct stat st; - if (stat(path, &st) == 0) { - if (size) { - *size = st.st_size; - } - return 0; // success - } else { - return errno; // return the specific error code - } - -} - -int core_fileopen(const char *path, void **handle) { - int *fd = user_malloc(sizeof(int)); - if (!fd) return -ENOMEM; - *fd = open(path, O_RDONLY); - if (*fd < 0) { - user_free(fd); - return -errno; - } - *handle = fd; - return 0; -} - -int core_fileread(void *handle, void *buffer, size_t size) { - int fd = *(int *)handle; - ssize_t bytes_read = read(fd, buffer, size); - if (bytes_read < 0) return -errno; - if ((size_t)bytes_read != size) return -EIO; - return 0; -} - -int core_fileclose(void *handle) { - int fd = *(int *)handle; - int ret = close(fd); - user_free(handle); - return ret; -} - -static int lsdir(const char *path) { - DIR *dirp; - struct dirent *entry; - - dirp = opendir(path); - if (!dirp) { - LOG_ERR("Error opening dir %s [%d]", path, errno); - return -errno; - } - - while ((entry = readdir(dirp)) != NULL) { - LOG_DBG("Found: %s", entry->d_name); - } - - if (closedir(dirp) < 0) { - LOG_ERR("Error closing dir [%d]", errno); - return -errno; - } - - return 0; -} - -void ocre_app_storage_init() { - struct stat st; - - if (stat(OCRE_BASE_PATH, &st) == -1) { - if (mkdir(OCRE_BASE_PATH, 0755) < 0) { - LOG_ERR("Failed to create directory %s [%d]", OCRE_BASE_PATH, errno); - } - } - - if (stat(APP_RESOURCE_PATH, &st) == -1) { - if (mkdir(APP_RESOURCE_PATH, 0755) < 0) { - LOG_ERR("Failed to create directory %s [%d]", APP_RESOURCE_PATH, errno); - } - } - - if (stat(PACKAGE_BASE_PATH, &st) == -1) { - if (mkdir(PACKAGE_BASE_PATH, 0755) < 0) { - LOG_ERR("Failed to create directory %s [%d]", PACKAGE_BASE_PATH, errno); - } - } - - if (stat(CONFIG_PATH, &st) == -1) { - if (mkdir(CONFIG_PATH, 0755) < 0) { - LOG_ERR("Failed to create directory %s [%d]", CONFIG_PATH, errno); - } - } - -#ifdef CONFIG_OCRE_CONTAINER_FILESYSTEM - if (stat(CONTAINER_FS_PATH, &st) == -1) { - if (mkdir(CONTAINER_FS_PATH, 0755) < 0) { - LOG_ERR("Failed to create directory %s [%d]", CONTAINER_FS_PATH, errno); - } - } -#endif - - lsdir(OCRE_BASE_PATH); -} diff --git a/src/shared/platform/posix/core_internal.h b/src/shared/platform/posix/core_internal.h deleted file mode 100644 index 0278daef..00000000 --- a/src/shared/platform/posix/core_internal.h +++ /dev/null @@ -1,289 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef OCRE_CORE_INTERNAL_H -#define OCRE_CORE_INTERNAL_H - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -// Config macros -#define CONFIG_OCRE_CONTAINER_MESSAGING /*!< Enable container messaging support */ -#define CONFIG_OCRE_NETWORKING /*!< Enable networking support */ -#define CONFIG_OCRE_CONTAINER_FILESYSTEM -#define CONFIG_OCRE_CONTAINER_WAMR_TERMINATION -#define CONFIG_OCRE_TIMER - -// Base paths for the application -#define OCRE_BASE_PATH "./ocre_data" /*!< Base directory for Ocre resources */ - -#define APP_RESOURCE_PATH OCRE_BASE_PATH "/images" /*!< Path to container images */ -#define PACKAGE_BASE_PATH OCRE_BASE_PATH "/manifests" /*!< Path to package manifests */ -#define CONFIG_PATH OCRE_BASE_PATH "/config" /*!< Path to configuration files */ - -/** - * @brief Path for container filesystem root - */ -#define CONTAINER_FS_PATH OCRE_BASE_PATH "/cfs" - -/** - * @brief Ignore Zephyr's log module registration on POSIX. - */ -#define LOG_MODULE_REGISTER(name, level) -#define LOG_MODULE_DECLARE(name, level) - - -/* - * @brief Log level priority definitions (highest to lowest) - */ -#define APP_LOG_LEVEL_ERR 1 -#define APP_LOG_LEVEL_WRN 2 -#define APP_LOG_LEVEL_INF 3 -#define APP_LOG_LEVEL_DBG 4 - -/* - * @brief Determine the current log level based on CONFIG defines - * Priority: CONFIG_LOG_LVL_ERR > CONFIG_LOG_LVL_WRN > CONFIG_LOG_LVL_INF > CONFIG_LOG_LVL_DBG - * If none specified, default to INFO level - */ -#if defined(CONFIG_LOG_LVL_ERR) - #define APP_CURRENT_LOG_LEVEL APP_LOG_LEVEL_ERR -#elif defined(CONFIG_LOG_LVL_WRN) - #define APP_CURRENT_LOG_LEVEL APP_LOG_LEVEL_WRN -#elif defined(CONFIG_LOG_LVL_INF) - #define APP_CURRENT_LOG_LEVEL APP_LOG_LEVEL_INF -#elif defined(CONFIG_LOG_LVL_DBG) - #define APP_CURRENT_LOG_LEVEL APP_LOG_LEVEL_DBG -#else - #define APP_CURRENT_LOG_LEVEL APP_LOG_LEVEL_INF /* Default to INFO level */ -#endif - -/** - * @brief Log an error message (always shown if ERR level or higher). - */ -#if APP_CURRENT_LOG_LEVEL >= APP_LOG_LEVEL_ERR - #define LOG_ERR(fmt, ...) printf("[ERROR] " fmt "\n", ##__VA_ARGS__) -#else - #define LOG_ERR(fmt, ...) do { } while(0) -#endif - -/** - * @brief Log a warning message (shown if WRN level or higher). - */ -#if APP_CURRENT_LOG_LEVEL >= APP_LOG_LEVEL_WRN - #define LOG_WRN(fmt, ...) printf("[WARNING] " fmt "\n", ##__VA_ARGS__) -#else - #define LOG_WRN(fmt, ...) do { } while(0) -#endif - -/** - * @brief Log an informational message (shown if INF level or higher). - */ -#if APP_CURRENT_LOG_LEVEL >= APP_LOG_LEVEL_INF - #define LOG_INF(fmt, ...) printf("[INFO] " fmt "\n", ##__VA_ARGS__) -#else - #define LOG_INF(fmt, ...) do { } while(0) -#endif - -/** - * @brief Log a debug message (shown only if DBG level). - */ -#if APP_CURRENT_LOG_LEVEL >= APP_LOG_LEVEL_DBG - #define LOG_DBG(fmt, ...) printf("[DEBUG] " fmt "\n", ##__VA_ARGS__) -#else - #define LOG_DBG(fmt, ...) do { } while(0) -#endif - -// Constants - -/** - * @brief Sets the value of argc for internal use. - * - * This function stores the argc value passed from main - * so that other functions in the module can access it - * without relying on global variables. - * - * @param argc The argument count from main. - */ -void set_argc(int argc); - -/** - * @brief Maximum length for SHA256 string representations. - */ -#define OCRE_SHA256_LEN 128 - -/** - * @brief Maximum number of containers supported. - */ -#define CONFIG_MAX_CONTAINERS 10 - -/** - * @brief Default stack size for container supervisor threads (in bytes). - */ -#define OCRE_CS_THREAD_STACK_SIZE (1024 * 1024) - -/** - * @brief Application version string. - */ -#ifndef APP_VERSION_STRING -#define APP_VERSION_STRING "0.0.0-dev" -#endif /* APP_VERSION_STRING */ - -/** - * @brief Default heap buffer size for WAMR (in bytes). - */ -#define CONFIG_OCRE_WAMR_HEAP_BUFFER_SIZE 512000 - -/** - * @brief Default heap size for a container (in bytes). - */ -#define CONFIG_OCRE_CONTAINER_DEFAULT_HEAP_SIZE 4096 - -/** - * @brief Default stack size for a container (in bytes). - */ -#define CONFIG_OCRE_CONTAINER_DEFAULT_STACK_SIZE 4096 * 16 - -/** - * @brief Default stack size for container threads (in bytes). - */ -#define CONTAINER_THREAD_STACK_SIZE 1024 * 1024 - -/** - * @brief Structure representing a thread in the Ocre runtime. - */ -struct core_thread { - pthread_t tid; /*!< POSIX thread identifier */ - void *stack; /*!< Pointer to thread stack memory */ - size_t stack_size; /*!< Size of the thread stack */ - uint32_t user_options; /*!< User-defined options for the thread */ -}; - -/** - * @brief Structure representing a mutex in the Ocre runtime. - */ -struct core_mutex { - pthread_mutex_t native_mutex; /*!< POSIX mutex */ -}; - -#define MQ_DEFAULT_PRIO 0 /*!< Default message queue priority */ - -/** - * @brief Structure representing a message queue in the Ocre runtime. - */ -struct core_mq { - mqd_t msgq; /*!< POSIX message queue descriptor */ -}; - -/** - * @brief Timer callback function type. - * - * @param user_data Pointer to user data passed to the callback. - */ -typedef void (*core_timer_callback_t)(void *user_data); - -/** - * @brief Structure representing a timer in the Ocre runtime. - */ -struct core_timer { - timer_t timerid; /*!< POSIX timer identifier */ - core_timer_callback_t cb; /*!< Timer callback function */ - void *user_data; /*!< User data for the callback */ -}; - -/* Generic singly-linked list iteration macros */ -#define CONTAINER_OF(ptr, type, member) \ - ((type *)((char *)(ptr) - offsetof(type, member))) - -#define CORE_SLIST_FOR_EACH_CONTAINER_SAFE(list, var, tmp, member) \ - for (var = (list)->head ? CONTAINER_OF((list)->head, __typeof__(*var), member) : NULL, \ - tmp = var ? (var->member.next ? CONTAINER_OF(var->member.next, __typeof__(*var), member) : NULL) : NULL; \ - var; \ - var = tmp, tmp = tmp ? (tmp->member.next ? CONTAINER_OF(tmp->member.next, __typeof__(*var), member) : NULL) : NULL) - -#define CORE_SLIST_FOR_EACH_CONTAINER(list, var, member) \ - for (var = (list)->head ? CONTAINER_OF((list)->head, __typeof__(*var), member) : NULL; \ - var; \ - var = var->member.next ? CONTAINER_OF(var->member.next, __typeof__(*var), member) : NULL) - -/** - * @brief Structure representing a node in a singly-linked list. - */ -typedef struct core_snode { - struct core_snode *next; /*!< Pointer to the next node in the list */ -} core_snode_t; - -/** - * @brief Structure representing a singly-linked list for POSIX platform. - */ -typedef struct { - core_snode_t *head; /*!< Pointer to the first node in the list */ - core_snode_t *tail; /*!< Pointer to the last node in the list */ -} core_slist_t; - -/** - * @brief Initialize a singly-linked list. - * - * @param list Pointer to the list to initialize. - */ -void core_slist_init(core_slist_t *list); - -/** - * @brief Append a node to the end of a singly-linked list. - * - * @param list Pointer to the list to append to. - * @param node Pointer to the node to append. - */ -void core_slist_append(core_slist_t *list, core_snode_t *node); - -/** - * @brief Remove a node from a singly-linked list. - * - * @param list Pointer to the list to remove from. - * @param prev Pointer to the previous node (or NULL if removing head). - * @param node Pointer to the node to remove. - */ -void core_slist_remove(core_slist_t *list, core_snode_t *prev, core_snode_t *node); - -/** - * @brief Spinlock type for POSIX platform (simulated using mutex). - */ -typedef struct { - pthread_mutex_t mutex; /*!< POSIX mutex for spinlock simulation */ -} core_spinlock_t; - -/** - * @brief Spinlock key type for POSIX platform. - */ -typedef int core_spinlock_key_t; - -/** - * @brief Generic event queue structure for POSIX platform. - * - * A thread-safe circular buffer implementation that can store - * any type of data items with configurable size and capacity. - */ -typedef struct { - void *buffer; /*!< Dynamically allocated buffer for queue items */ - size_t item_size; /*!< Size of each individual item in bytes */ - size_t max_items; /*!< Maximum number of items the queue can hold */ - size_t count; /*!< Current number of items in the queue */ - size_t head; /*!< Index of the next item to be read */ - size_t tail; /*!< Index where the next item will be written */ - pthread_mutex_t mutex; /*!< Mutex for thread-safe access */ - pthread_cond_t cond; /*!< Condition variable for signaling */ -} core_eventq_t; - -#endif /* OCRE_CORE_INTERNAL_H */ diff --git a/src/shared/platform/posix/core_memory.c b/src/shared/platform/posix/core_memory.c deleted file mode 100644 index 04d0ae7d..00000000 --- a/src/shared/platform/posix/core_memory.c +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "ocre_core_external.h" - -#include - -void *core_malloc(size_t size) { - return malloc(size); -} - -void core_free(void *ptr) { - free(ptr); -} - -void *user_malloc(size_t size) { - return malloc(size); -} - -void user_free(void *ptr) { - free(ptr); -} - -void *user_realloc(void *ptr, size_t size) { - return realloc(ptr, size); -} diff --git a/src/shared/platform/posix/core_misc.c b/src/shared/platform/posix/core_misc.c deleted file mode 100644 index 069c1735..00000000 --- a/src/shared/platform/posix/core_misc.c +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "ocre_core_external.h" - -#include -#include -#include -#include - -void core_sleep_ms(int milliseconds) -{ - struct timespec ts; - int res; - - if (milliseconds < 0) - { - errno = EINVAL; - fprintf(stderr, "core_sleep_ms: Invalid milliseconds value (%d)\n", milliseconds); - return; - } - - ts.tv_sec = milliseconds / 1000; - ts.tv_nsec = (milliseconds % 1000) * 1000000; - - do { - res = nanosleep(&ts, &ts); - if (res && errno != EINTR) { - fprintf(stderr, "core_sleep_ms: nanosleep failed (errno=%d)\n", errno); - } - } while (res && errno == EINTR); -} - -void core_yield(void) { - sched_yield(); -} - -uint32_t core_uptime_get(void) { - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return (uint32_t)(ts.tv_sec * 1000 + ts.tv_nsec / 1000000); -} - -core_spinlock_key_t core_spinlock_lock(core_spinlock_t *lock) { - pthread_mutex_lock(&lock->mutex); - return 0; -} - -void core_spinlock_unlock(core_spinlock_t *lock, core_spinlock_key_t key) { - (void)key; - pthread_mutex_unlock(&lock->mutex); -} diff --git a/src/shared/platform/posix/core_mq.c b/src/shared/platform/posix/core_mq.c deleted file mode 100644 index e9afa8c8..00000000 --- a/src/shared/platform/posix/core_mq.c +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "ocre_core_external.h" - -#include -#include - -int core_mq_init(core_mq_t *mq, const char *name, size_t msg_size, uint32_t max_msgs) -{ - struct mq_attr attr; - - // Configure the message queue attributes - attr.mq_flags = 0; // Blocking mode - attr.mq_maxmsg = max_msgs; // Maximum number of messages in the queue - attr.mq_msgsize = msg_size; // Size of each message - attr.mq_curmsgs = 0; // Number of messages currently in the queue - - // Try to unlink the message queue, but ignore error if it doesn't exist - if (mq_unlink(name) == -1 && errno != ENOENT) - { - perror("Main: mq_unlink"); - return -errno; - } - - // Create the message queue - mq->msgq = mq_open(name, O_CREAT | O_RDWR, 0644, &attr); - if (mq->msgq == (mqd_t)-1) { - perror("Failed to create message queue"); - return -errno; - } - return 0; -} - -int core_mq_send(core_mq_t *mq, const void *data, size_t msg_len) -{ - int ret = mq_send(mq->msgq, (const char *)data, msg_len, MQ_DEFAULT_PRIO); - - if (ret == -1) { - perror("Failed to send message"); - } - return ret; -} - -int core_mq_recv(core_mq_t *mq, void *data) -{ - struct mq_attr attr; - unsigned int priority; - - // Get message queue attributes - if (mq_getattr(mq->msgq, &attr) == -1) { - perror("Failed to get message queue attributes"); - return -errno; - } - ssize_t bytes_received = mq_receive(mq->msgq, (char *)data, attr.mq_msgsize, &priority); - if (bytes_received == -1) { - perror("Failed to receive message"); - return -errno; - } - return bytes_received; -} diff --git a/src/shared/platform/posix/core_mutex.c b/src/shared/platform/posix/core_mutex.c deleted file mode 100644 index a13753da..00000000 --- a/src/shared/platform/posix/core_mutex.c +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "ocre_core_external.h" -#include -#include - -int core_mutex_init(core_mutex_t *mutex) { - if (!mutex) return -1; - return pthread_mutex_init(&mutex->native_mutex, NULL); -} - -int core_mutex_destroy(core_mutex_t *mutex) { - return pthread_mutex_destroy(&mutex->native_mutex); -} - -int core_mutex_lock(core_mutex_t *mutex) { - return pthread_mutex_lock(&mutex->native_mutex); -} - -int core_mutex_unlock(core_mutex_t *mutex) { - return pthread_mutex_unlock(&mutex->native_mutex); -} diff --git a/src/shared/platform/posix/core_slist.c b/src/shared/platform/posix/core_slist.c deleted file mode 100644 index 1def4404..00000000 --- a/src/shared/platform/posix/core_slist.c +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "ocre_core_external.h" - -void core_slist_init(core_slist_t *list) { - list->head = NULL; - list->tail = NULL; -} - -void core_slist_append(core_slist_t *list, core_snode_t *node) { - node->next = NULL; - if (list->tail) { - list->tail->next = node; - } else { - list->head = node; - } - list->tail = node; -} - -void core_slist_remove(core_slist_t *list, core_snode_t *prev, core_snode_t *node) { - if (prev) { - prev->next = node->next; - } else { - list->head = node->next; - } - if (list->tail == node) { - list->tail = prev; - } -} diff --git a/src/shared/platform/posix/core_thread.c b/src/shared/platform/posix/core_thread.c deleted file mode 100644 index f6763e5b..00000000 --- a/src/shared/platform/posix/core_thread.c +++ /dev/null @@ -1,77 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "ocre_core_external.h" -#include -#include -#include -#include -#include -#include - - -static void *thread_entry(void *arg) { - struct { - core_thread_func_t func; - void *user_arg; - char name[16]; - } *entry = arg; - - if (entry->name[0]) - pthread_setname_np(pthread_self(), entry->name); - - entry->func(entry->user_arg); - free(entry); - return NULL; -} - -int core_thread_create(core_thread_t *thread, core_thread_func_t func, void *arg, const char *name, size_t stack_size, int priority) { - if (!thread || !func) return -1; - pthread_attr_t attr; - int ret; - - if (stack_size < PTHREAD_STACK_MIN) { - fprintf(stderr, "STACK_SIZE must be at least PTHREAD_STACK_MIN (%zu)\n", (size_t)PTHREAD_STACK_MIN); - return -1; - } - - thread->stack_size = stack_size; - if (posix_memalign(&thread->stack, sysconf(_SC_PAGESIZE), stack_size) != 0) { - perror("posix_memalign"); - return -1; - } - - pthread_attr_init(&attr); - pthread_attr_setstack(&attr, thread->stack, stack_size); - - // Prepare entry struct for name passing - struct { - core_thread_func_t func; - void *user_arg; - char name[16]; - } *entry = malloc(sizeof(*entry)); - entry->func = func; - entry->user_arg = arg; - strncpy(entry->name, name ? name : "", sizeof(entry->name) - 1); - entry->name[sizeof(entry->name) - 1] = '\0'; - - ret = pthread_create(&thread->tid, &attr, thread_entry, entry); - pthread_attr_destroy(&attr); - if (ret != 0) { - free(thread->stack); - free(entry); - return -1; - } - return 0; -} - -void core_thread_destroy(core_thread_t *thread) { - if (!thread) return; - pthread_cancel(thread->tid); - pthread_join(thread->tid, NULL); - free(thread->stack); -} diff --git a/src/shared/platform/posix/core_timer.c b/src/shared/platform/posix/core_timer.c deleted file mode 100644 index 0692de34..00000000 --- a/src/shared/platform/posix/core_timer.c +++ /dev/null @@ -1,52 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "ocre_core_external.h" - -#include -#include -#include -#include - -static void posix_timer_cb(union sigval sv) { - core_timer_t *timer = (core_timer_t *)sv.sival_ptr; - if (timer->cb) { - timer->cb(timer->user_data); - } -} - -int core_timer_init(core_timer_t *timer, core_timer_callback_t cb, void *user_data) { - if (!timer) return -1; - struct sigevent sev = {0}; - timer->cb = cb; - timer->user_data = user_data; - sev.sigev_notify = SIGEV_THREAD; - sev.sigev_notify_function = posix_timer_cb; - sev.sigev_value.sival_ptr = timer; - return timer_create(CLOCK_REALTIME, &sev, &timer->timerid); -} - -int core_timer_start(core_timer_t *timer, int timeout_ms, int period_ms) { - if (!timer) return -1; - struct itimerspec its; - if (timeout_ms == 0 && period_ms > 0) { - its.it_value.tv_sec = period_ms / 1000; - its.it_value.tv_nsec = (period_ms % 1000) * 1000000; - } else { - its.it_value.tv_sec = timeout_ms / 1000; - its.it_value.tv_nsec = (timeout_ms % 1000) * 1000000; - } - its.it_interval.tv_sec = period_ms / 1000; - its.it_interval.tv_nsec = (period_ms % 1000) * 1000000; - return timer_settime(timer->timerid, 0, &its, NULL); -} - -int core_timer_stop(core_timer_t *timer) { - if (!timer) return -1; - struct itimerspec its = {0}; - return timer_settime(timer->timerid, 0, &its, NULL); -} diff --git a/src/shared/platform/posix/ocre_internal.cmake b/src/shared/platform/posix/ocre_internal.cmake deleted file mode 100644 index 675dbb3e..00000000 --- a/src/shared/platform/posix/ocre_internal.cmake +++ /dev/null @@ -1,117 +0,0 @@ -include(CheckPIESupported) -option(BUILD_SHARED_LIBS "Build using shared libraries" OFF) -set (CMAKE_VERBOSE_MAKEFILE OFF) - -# Build third-party libs -add_subdirectory(${OCRE_ROOT_DIR}/src/ocre/utils/c-smf) - -# Reset default linker flags -set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") -set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") - -# Set WAMR_BUILD_TARGET, currently values supported: -# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", -# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]" -if (NOT DEFINED WAMR_BUILD_TARGET) - if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)") - set (WAMR_BUILD_TARGET "AARCH64") - if (NOT DEFINED WAMR_BUILD_SIMD) - set (WAMR_BUILD_SIMD 1) - endif () - elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") - set (WAMR_BUILD_TARGET "RISCV64") - elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) - set (WAMR_BUILD_TARGET "X86_64") - if (NOT DEFINED WAMR_BUILD_SIMD) - set (WAMR_BUILD_SIMD 1) - endif () - elseif (CMAKE_SIZEOF_VOID_P EQUAL 4) - set (WAMR_BUILD_TARGET "X86_32") - else () - message(SEND_ERROR "Unsupported build target platform!") - endif () -endif () - -# WAMR Options -set (WAMR_BUILD_PLATFORM "linux") -set (WAMR_BUILD_INTERP 1) -set (WAMR_BUILD_FAST_INTERP 0) -set (WAMR_BUILD_AOT 0) -set (WAMR_BUILD_JIT 0) -set (WAMR_BUILD_LIBC_BUILTIN 0) -set (WAMR_BUILD_LIBC_WASI 1) -set (WAMR_BUILD_LIB_PTHREAD 1) -set (WAMR_BUILD_REF_TYPES 1) -set (WASM_ENABLE_LOG 1) -set (WAMR_BUILD_SHARED_HEAP 1) - -if (NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_POOL) - set (WAMR_BUILD_GLOBAL_HEAP_POOL 1) -endif () -if (NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_SIZE) - set (WAMR_BUILD_GLOBAL_HEAP_SIZE 32767) -endif () - -set (WAMR_ROOT_DIR "wasm-micro-runtime") -include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) - -check_pie_supported() - -set(component_sources - # Component support - ${OCRE_ROOT_DIR}/src/ocre/component/component.c - - # Components - ${OCRE_ROOT_DIR}/src/ocre/ocre_container_runtime/ocre_container_runtime.c - ${OCRE_ROOT_DIR}/src/ocre/components/container_supervisor/cs_main.c - ${OCRE_ROOT_DIR}/src/ocre/components/container_supervisor/cs_sm.c - ${OCRE_ROOT_DIR}/src/ocre/components/container_supervisor/cs_sm_impl.c -) - -set(lib_sources - ${OCRE_ROOT_DIR}/src/ocre/sm/sm.c - # Platform - ${OCRE_ROOT_DIR}/src/shared/platform/posix/core_fs.c - ${OCRE_ROOT_DIR}/src/shared/platform/posix/core_thread.c - ${OCRE_ROOT_DIR}/src/shared/platform/posix/core_mutex.c - ${OCRE_ROOT_DIR}/src/shared/platform/posix/core_mq.c - ${OCRE_ROOT_DIR}/src/shared/platform/posix/core_misc.c - ${OCRE_ROOT_DIR}/src/shared/platform/posix/core_memory.c - ${OCRE_ROOT_DIR}/src/shared/platform/posix/core_timer.c - ${OCRE_ROOT_DIR}/src/shared/platform/posix/core_slist.c - ${OCRE_ROOT_DIR}/src/shared/platform/posix/core_eventq.c - # APIs - ${OCRE_ROOT_DIR}/src/ocre/api/ocre_api.c - ${OCRE_ROOT_DIR}/src/ocre/api/ocre_common.c - ${OCRE_ROOT_DIR}/src/ocre/ocre_timers/ocre_timer.c - ${OCRE_ROOT_DIR}/src/ocre/ocre_messaging/ocre_messaging.c - # Utils - ${OCRE_ROOT_DIR}/src/ocre/utils/strlcat.c -) - -include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) - -set(app_sources - ${OCRE_ROOT_DIR}/src/samples-mini/posix/main.c - ${UNCOMMON_SHARED_SOURCE} - ${WAMR_RUNTIME_LIB_SOURCE} - ${lib_sources} - ${component_sources} -) - -add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) -target_link_libraries(vmlib ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl -lpthread) - -add_executable(app ${app_sources}) -target_include_directories(app PUBLIC - ${OCRE_ROOT_DIR}/src - ${OCRE_ROOT_DIR}/src/ocre - ${OCRE_ROOT_DIR}/src/shared/platform -) - -set_target_properties(app PROPERTIES POSITION_INDEPENDENT_CODE ON) -target_link_libraries(app smf vmlib -lm -lpthread) - -add_compile_options(-O0 -Wno-unknown-attributes -Wall -Wextra) - -add_dependencies(app generate_messages) diff --git a/src/shared/platform/zephyr/core_eventq.c b/src/shared/platform/zephyr/core_eventq.c deleted file mode 100644 index 7ec83f7a..00000000 --- a/src/shared/platform/zephyr/core_eventq.c +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "ocre_core_external.h" -#include -#include - -int core_eventq_init(core_eventq_t *eventq, size_t item_size, size_t max_items) { - eventq->buffer = core_malloc(item_size * max_items); - if (!eventq->buffer) { - return -ENOMEM; - } - eventq->item_size = item_size; - eventq->max_items = max_items; - - k_msgq_init(&eventq->msgq, (char *)eventq->buffer, item_size, max_items); - return 0; -} - -int core_eventq_peek(core_eventq_t *eventq, void *event) { - int ret = k_msgq_peek(&eventq->msgq, event); - if (ret == 0) { - return 0; - } else if (ret == -ENOMSG) { - return -ENOMSG; - } else { - return ret; - } -} - -int core_eventq_get(core_eventq_t *eventq, void *event) { - int ret = k_msgq_get(&eventq->msgq, event, K_NO_WAIT); - if (ret == 0) { - return 0; - } else if (ret == -ENOMSG) { - return -ENOENT; - } else { - return ret; - } -} - -int core_eventq_put(core_eventq_t *eventq, const void *event) { - int ret = k_msgq_put(&eventq->msgq, event, K_NO_WAIT); - if (ret == 0) { - return 0; - } else if (ret == -ENOMSG) { - return -ENOMEM; - } else { - return ret; - } -} - -void core_eventq_destroy(core_eventq_t *eventq) { - if (eventq->buffer) { - core_free(eventq->buffer); - eventq->buffer = NULL; - } -} - - diff --git a/src/shared/platform/zephyr/core_fs.c b/src/shared/platform/zephyr/core_fs.c deleted file mode 100644 index 42f1d614..00000000 --- a/src/shared/platform/zephyr/core_fs.c +++ /dev/null @@ -1,270 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -LOG_MODULE_REGISTER(filesystem, OCRE_LOG_LEVEL); - -#include -#include -#include -#include -#include -#include -#include -#include -#include "ocre_core_external.h" - -#define MAX_PATH_LEN LFS_NAME_MAX - -#ifdef CONFIG_SHELL -#define print(shell, level, fmt, ...) \ - do { \ - shell_fprintf(shell, level, fmt, ##__VA_ARGS__); \ - } while (false) -#else -#define print(shell, level, fmt, ...) \ - do { \ - printk(fmt, ##__VA_ARGS__); \ - } while (false) -#endif - -int core_construct_filepath(char *path, size_t len, char *name) { - return snprintf(path, len, "/lfs/ocre/images/%s.bin", name); -} - -int core_filestat(const char *path, size_t *size) { - struct fs_dirent entry; - int ret = fs_stat(path, &entry); - if (ret == 0 && size) { - *size = entry.size; - } - return ret; -} - -int core_fileopen(const char *path, void **handle) { - struct fs_file_t *file = user_malloc(sizeof(struct fs_file_t)); - if (!file) return -ENOMEM; - fs_file_t_init(file); - int ret = fs_open(file, path, FS_O_READ); - if (ret < 0) { - user_free(file); - return ret; - } - *handle = file; - return 0; -} - -int core_fileread(void *handle, void *buffer, size_t size) { - struct fs_file_t *file = (struct fs_file_t *)handle; - return fs_read(file, buffer, size); -} - -int core_fileclose(void *handle) { - struct fs_file_t *file = (struct fs_file_t *)handle; - int ret = fs_close(file); - user_free(file); - return ret; -} - -static int lsdir(const char *path) { - int res; - struct fs_dir_t dirp; - static struct fs_dirent entry; - - fs_dir_t_init(&dirp); - - /* Verify fs_opendir() */ - res = fs_opendir(&dirp, path); - if (res) { - LOG_ERR("Error opening dir %s [%d]\n", path, res); - return res; - } - - for (;;) { - // Verify fs_readdir() - res = fs_readdir(&dirp, &entry); - - // entry.name[0] == 0 means end-of-dir - if (res || entry.name[0] == 0) { - if (res < 0) { - LOG_ERR("Error reading dir [%d]\n", res); - } - break; - } - } - - // Verify fs_closedir() - fs_closedir(&dirp); - - return res; -} - -static int littlefs_flash_erase(unsigned int id) { - const struct flash_area *pfa; - int rc; - - rc = flash_area_open(id, &pfa); - if (rc < 0) { - LOG_ERR("FAIL: unable to find flash area %u: %d\n", id, rc); - return rc; - } - - LOG_PRINTK("Area %u at 0x%x on %s for %u bytes\n", id, (unsigned int)pfa->fa_off, pfa->fa_dev->name, - (unsigned int)pfa->fa_size); - - rc = flash_area_erase(pfa, 0, pfa->fa_size); - - if (rc < 0) { - LOG_ERR("Failed to erase flash: %d", rc); - } else { - LOG_INF("Successfully erased flash"); - } - - flash_area_close(pfa); - - return rc; -} - -#define PARTITION_NODE DT_NODELABEL(lfs1) - -#if DT_NODE_EXISTS(PARTITION_NODE) -FS_FSTAB_DECLARE_ENTRY(PARTITION_NODE); -#else /* PARTITION_NODE */ -FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(user_data); -static struct fs_mount_t lfs_storage_mnt = { - .type = FS_LITTLEFS, - .fs_data = &user_data, - .storage_dev = (void *)FIXED_PARTITION_ID(user_data_partition), - .mnt_point = FS_MOUNT_POINT, -}; -#endif /* PARTITION_NODE */ - -struct fs_mount_t *mp = -#if DT_NODE_EXISTS(PARTITION_NODE) - &FS_FSTAB_ENTRY(PARTITION_NODE) -#else - &lfs_storage_mnt -#endif - ; - -static int littlefs_mount(struct fs_mount_t *mp) { - int rc = 0; - - /* Do not mount if auto-mount has been enabled */ -#if !DT_NODE_EXISTS(PARTITION_NODE) || !(FSTAB_ENTRY_DT_MOUNT_FLAGS(PARTITION_NODE) & FS_MOUNT_FLAG_AUTOMOUNT) - rc = fs_mount(mp); - if (rc < 0) { - LOG_ERR("FAIL: mount id %" PRIuPTR " at %s: %d\n", (uintptr_t)mp->storage_dev, mp->mnt_point, rc); - return rc; - } - LOG_INF("%s mount: %d\n", mp->mnt_point, rc); -#else - LOG_INF("%s automounted\n", mp->mnt_point); -#endif - - return rc; -} - -#ifdef CONFIG_APP_LITTLEFS_STORAGE_BLK_SDMMC -struct fs_littlefs lfsfs; -static struct fs_mount_t __mp = { - .type = FS_LITTLEFS, - .fs_data = &lfsfs, - .flags = FS_MOUNT_FLAG_USE_DISK_ACCESS, -}; - -struct fs_mount_t *mp = &__mp; - -static int littlefs_mount(struct fs_mount_t *mp) { - static const char *disk_mount_pt = "/" CONFIG_SDMMC_VOLUME_NAME ":"; - static const char *disk_pdrv = CONFIG_SDMMC_VOLUME_NAME; - - mp->storage_dev = (void *)disk_pdrv; - mp->mnt_point = disk_mount_pt; - - return fs_mount(mp); -} -#endif /* CONFIG_APP_LITTLEFS_STORAGE_BLK_SDMMC */ - -void ocre_app_storage_init() { - struct fs_dirent entry; - struct fs_statvfs sbuf; - int rc; - - rc = littlefs_mount(mp); - if (rc < 0) { - return; - } - - rc = fs_statvfs(mp->mnt_point, &sbuf); - if (rc < 0) { - LOG_ERR("FAILR statvfs: %d", rc); - return; - } - - LOG_DBG("%s: bsize = %lu ; frsize = %lu ;" - " blocks = %lu ; bfree = %lu", - mp->mnt_point, sbuf.f_bsize, sbuf.f_frsize, sbuf.f_blocks, sbuf.f_bfree); - - rc = lsdir(mp->mnt_point); - if (rc < 0) { - LOG_ERR("FAIL: lsdir %s: %d", mp->mnt_point, rc); - } - - // Create the core directories if they don't exist - if (fs_stat(OCRE_BASE_PATH, &entry) == -ENOENT) { - fs_mkdir(OCRE_BASE_PATH); - } - - if (fs_stat(APP_RESOURCE_PATH, &entry) == -ENOENT) { - fs_mkdir(APP_RESOURCE_PATH); - } - - if (fs_stat(PACKAGE_BASE_PATH, &entry) == -ENOENT) { - fs_mkdir(PACKAGE_BASE_PATH); - } - - if (fs_stat(CONFIG_PATH, &entry) == -ENOENT) { - fs_mkdir(CONFIG_PATH); - } - -#ifdef CONFIG_OCRE_CONTAINER_FILESYSTEM - if (fs_stat(CONTAINER_FS_PATH, &entry) == -ENOENT) { - fs_mkdir(CONTAINER_FS_PATH); - } -#endif -} - -static int cmd_flash_format(const struct shell *shell, size_t argc, char *argv[]) { - int rc; - fs_unmount(mp); - - // FIXME: if erasing the whole chip, could cause problems - // https://github.com/zephyrproject-rtos/zephyr/issues/56442 - rc = littlefs_flash_erase((uintptr_t)mp->storage_dev); - - if (rc < 0) { - print(shell, SHELL_WARNING, "Format failed: %d\n", rc); - } else { - print(shell, SHELL_NORMAL, "Format succeeded\n"); - } - - if (rc == 0) { - LOG_INF("Mounting..."); - rc = littlefs_mount(mp); - } - - return rc; -} - -SHELL_STATIC_SUBCMD_SET_CREATE(flash_commands, - SHELL_CMD(format, NULL, "Format the flash storage device (all user data will be lost)", - cmd_flash_format), - SHELL_SUBCMD_SET_END); - -SHELL_CMD_REGISTER(user_storage, &flash_commands, "User storage management", NULL); diff --git a/src/shared/platform/zephyr/core_internal.h b/src/shared/platform/zephyr/core_internal.h deleted file mode 100644 index 26e0f971..00000000 --- a/src/shared/platform/zephyr/core_internal.h +++ /dev/null @@ -1,209 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef OCRE_CORE_INTERNAL_H -#define OCRE_CORE_INTERNAL_H - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -// clang-format off - -/** - * @brief Filesystem mount point for Ocre resources. - */ -#define FS_MOUNT_POINT "/lfs" - -/** - * @brief Base directory for Ocre resources. - */ -#define OCRE_BASE_PATH FS_MOUNT_POINT "/ocre" - -/** - * @brief Path to container images. - */ -#define APP_RESOURCE_PATH OCRE_BASE_PATH "/images" - -/** - * @brief Path to package manifests. - */ -#define PACKAGE_BASE_PATH OCRE_BASE_PATH "/manifests" - -/** - * @brief Path to configuration files. - */ -#define CONFIG_PATH OCRE_BASE_PATH "/config/" - -/** - * @brief Path for container filesystem root - */ -#define CONTAINER_FS_PATH OCRE_BASE_PATH "/cfs" - -// Constants - -/** - * @brief Default stack size for container supervisor threads (in bytes). - */ -#define OCRE_CS_THREAD_STACK_SIZE 4096 - -/** - * @brief Default stack size for container threads (in bytes). - */ -#define CONTAINER_THREAD_STACK_SIZE 8192 - -/** - * @brief Default stack size for event threads (in bytes). - */ -#define EVENT_THREAD_STACK_SIZE 2048 - -/** - * @brief Maximum length for SHA256 string representations. - */ -#define OCRE_SHA256_LEN 128 - -/** - * @brief Structure representing a thread in the Ocre runtime (Zephyr). - */ -struct core_thread { - struct k_thread thread; /*!< Zephyr thread structure */ - k_tid_t tid; /*!< Zephyr thread identifier */ - k_thread_stack_t *stack; /*!< Pointer to thread stack memory */ - size_t stack_size; /*!< Size of the thread stack */ - uint32_t user_options; /*!< User-defined options for the thread */ -}; - -/** - * @brief Structure representing a mutex in the Ocre runtime (Zephyr). - */ -struct core_mutex { - struct k_mutex native_mutex; /*!< Zephyr native mutex */ -}; - -/** - * @brief Default timeout value for message queue operations. - */ -#define MQ_DEFAULT_TIMEOUT K_NO_WAIT - -/** - * @brief Structure representing a message queue in the Ocre runtime (Zephyr). - */ -struct core_mq { - struct k_msgq msgq; /*!< Zephyr message queue */ - char __aligned(4) *msgq_buffer; /*!< Message queue buffer (aligned) */ -}; - -/** - * @brief Timer callback function type. - * - * @param user_data Pointer to user data passed to the callback. - */ -typedef void (*core_timer_callback_t)(void *user_data); - -/** - * @brief Structure representing a timer in the Ocre runtime (Zephyr). - */ -struct core_timer { - struct k_timer timer; /*!< Zephyr timer structure */ - core_timer_callback_t cb; /*!< Timer callback function */ - void *user_data; /*!< User data for the callback */ -}; - -/* Generic singly-linked list iteration macros */ -#define CORE_SLIST_FOR_EACH_CONTAINER_SAFE SYS_SLIST_FOR_EACH_CONTAINER_SAFE -#define CORE_SLIST_FOR_EACH_CONTAINER SYS_SLIST_FOR_EACH_CONTAINER - -/** - * @brief Structure representing a node in a singly-linked list. - */ -#define core_snode_t sys_snode_t - -/** - * @brief Structure representing a singly-linked list for POSIX platform. - */ -#define core_slist_t sys_slist_t - -/** - * @brief Initialize a singly-linked list. - * - * @param list Pointer to the list to initialize. - */ -#define core_slist_init sys_slist_init - -/** - * @brief Append a node to the end of a singly-linked list. - * - * @param list Pointer to the list to append to. - * @param node Pointer to the node to append. - */ -#define core_slist_append sys_slist_append - -/** - * @brief Remove a node from a singly-linked list. - * - * @param list Pointer to the list to remove from. - * @param prev Pointer to the previous node (or NULL if removing head). - * @param node Pointer to the node to remove. - */ -#define core_slist_remove sys_slist_remove - -/* Zephyr-specific macros */ - -/** - * @brief Get system uptime in milliseconds. - * - * @return System uptime in milliseconds. - */ -#define core_uptime_get k_uptime_get_32 - -/** - * @brief Lock a spinlock and return the interrupt key. - * - * @param lock Pointer to the spinlock structure. - * @return Interrupt key to be used with unlock. - */ -#define core_spinlock_lock k_spin_lock - -/** - * @brief Unlock a spinlock using the interrupt key. - * - * @param lock Pointer to the spinlock structure. - * @param key Interrupt key returned from lock operation. - */ -#define core_spinlock_unlock k_spin_unlock - -/** - * @brief Spinlock type for Zephyr platform. - */ -typedef struct k_spinlock core_spinlock_t; - -/** - * @brief Spinlock key type for Zephyr platform. - */ -typedef k_spinlock_key_t core_spinlock_key_t; - -/** - * @brief Generic event queue structure for Zephyr platform. - * - * A thread-safe message queue implementation using Zephyr's k_msgq - * that can store any type of data items with configurable size and capacity. - */ -typedef struct { - void *buffer; /*!< Dynamically allocated buffer for queue items */ - size_t item_size; /*!< Size of each individual item in bytes */ - size_t max_items; /*!< Maximum number of items the queue can hold */ - struct k_msgq msgq; /*!< Zephyr message queue */ -} core_eventq_t; - -#endif diff --git a/src/shared/platform/zephyr/core_memory.c b/src/shared/platform/zephyr/core_memory.c deleted file mode 100644 index d295b32c..00000000 --- a/src/shared/platform/zephyr/core_memory.c +++ /dev/null @@ -1,49 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "ocre_core_external.h" - -#include -#include - -void *core_malloc(size_t size) { - return k_malloc(size); -} - -void core_free(void *ptr) { - k_free(ptr); -} - -#ifdef CONFIG_SHARED_MULTI_HEAP -void *user_malloc(size_t size) { - return shared_multi_heap_aligned_alloc(SMH_REG_ATTR_EXTERNAL, 32, size); -} - -void user_free(void *ptr) { - shared_multi_heap_free(ptr); -} - -void *user_realloc(void *ptr, size_t size) { - // TODO - return NULL; -} - -#else -#warning CONFIG_SHARED_MULTI_HEAP is not defined. Using internal RAM -void *user_malloc(size_t size) { - return k_malloc(size); -} - -void user_free(void *ptr) { - k_free(ptr); -} - -void *user_realloc(void *ptr, size_t size) { - return k_realloc(ptr, size); -} - -#endif diff --git a/src/shared/platform/zephyr/core_misc.c b/src/shared/platform/zephyr/core_misc.c deleted file mode 100644 index c689ee77..00000000 --- a/src/shared/platform/zephyr/core_misc.c +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "ocre_core_external.h" -#include - -void core_sleep_ms(int milliseconds) { - k_msleep(milliseconds); -} - -void core_yield(void) { - k_yield(); -} diff --git a/src/shared/platform/zephyr/core_mq.c b/src/shared/platform/zephyr/core_mq.c deleted file mode 100644 index c7c88665..00000000 --- a/src/shared/platform/zephyr/core_mq.c +++ /dev/null @@ -1,32 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "ocre_core_external.h" -#include -LOG_MODULE_DECLARE(platform_mq_component, OCRE_LOG_LEVEL); - -int core_mq_init(core_mq_t *mq, const char *name, size_t msg_size, uint32_t max_msgs) -{ - mq->msgq_buffer = k_malloc(msg_size * max_msgs); - k_msgq_init(&mq->msgq, mq->msgq_buffer, msg_size, max_msgs); - return 0; -} - -int core_mq_send(core_mq_t *mq, const void *data, size_t msg_len) -{ - int ret = k_msgq_put(&mq->msgq, data, MQ_DEFAULT_TIMEOUT); - - if (ret != 0) { - LOG_HEXDUMP_DBG(data, msg_len, "message"); - } - return ret; -} - -int core_mq_recv(core_mq_t *mq, void *data) -{ - return k_msgq_get(&mq->msgq, data, K_FOREVER); -} diff --git a/src/shared/platform/zephyr/core_mutex.c b/src/shared/platform/zephyr/core_mutex.c deleted file mode 100644 index bd8f8034..00000000 --- a/src/shared/platform/zephyr/core_mutex.c +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "ocre_core_external.h" -#include - -int core_mutex_init(core_mutex_t *mutex) { - if (!mutex) return -1; - k_mutex_init(&mutex->native_mutex); - return 0; -} - -int core_mutex_destroy(core_mutex_t *mutex) { - return 0; -} - -int core_mutex_lock(core_mutex_t *mutex) { - return k_mutex_lock(&mutex->native_mutex, K_FOREVER); -} - -int core_mutex_unlock(core_mutex_t *mutex) { - return k_mutex_unlock(&mutex->native_mutex); -} - diff --git a/src/shared/platform/zephyr/core_thread.c b/src/shared/platform/zephyr/core_thread.c deleted file mode 100644 index 7bbd6fdd..00000000 --- a/src/shared/platform/zephyr/core_thread.c +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "ocre_core_external.h" -#include -#include - - -static void thread_entry(void *arg1, void *arg2, void *arg3) { - core_thread_func_t func = (core_thread_func_t)arg2; - void *user_arg = arg3; - func(user_arg); -} - -int core_thread_create(core_thread_t *thread, core_thread_func_t func, void *arg, const char *name, size_t stack_size, int priority) { - if (!thread || !func) return -1; - thread->stack = k_thread_stack_alloc(stack_size, 0); - if (!thread->stack) return -1; - thread->tid = k_thread_create(&thread->thread, thread->stack, stack_size, - thread_entry, NULL, (void *)func, arg, - priority, 0, K_NO_WAIT); - if (name) - k_thread_name_set(thread->tid, name); - return thread->tid ? 0 : -1; -} - -void core_thread_destroy(core_thread_t *thread) { - if (!thread) return; - k_thread_abort(thread->tid); - k_thread_stack_free(thread->stack); -} diff --git a/src/shared/platform/zephyr/core_timer.c b/src/shared/platform/zephyr/core_timer.c deleted file mode 100644 index 10da2d32..00000000 --- a/src/shared/platform/zephyr/core_timer.c +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "ocre_core_external.h" -#include - - -static void zephyr_timer_cb(struct k_timer *ktimer) { - core_timer_t *otimer = CONTAINER_OF(ktimer, core_timer_t, timer); - if (otimer->cb) { - otimer->cb(otimer->user_data); - } -} - -int core_timer_init(core_timer_t *timer, core_timer_callback_t cb, void *user_data) { - if (!timer) return -1; - timer->cb = cb; - timer->user_data = user_data; - k_timer_init(&timer->timer, zephyr_timer_cb, NULL); - return 0; -} - -int core_timer_start(core_timer_t *timer, int timeout_ms, int period_ms) { - if (!timer) return -1; - k_timer_start(&timer->timer, K_MSEC(timeout_ms), K_MSEC(period_ms)); - return 0; -} - -int core_timer_stop(core_timer_t *timer) { - if (!timer) return -1; - k_timer_stop(&timer->timer); - return 0; -} diff --git a/src/shared/platform/zephyr/ocre_internal.cmake b/src/shared/platform/zephyr/ocre_internal.cmake deleted file mode 100644 index cccf6375..00000000 --- a/src/shared/platform/zephyr/ocre_internal.cmake +++ /dev/null @@ -1,125 +0,0 @@ -# Zephyr-specific version defines -message("VERSION NUMBER: ${VERSION_NUMBER}") -zephyr_compile_options(-DVERSION_INFO="${VERSION_NUMBER}") -message("BUILD DATE: ${BUILD_DATE}") -zephyr_compile_options(-DVERSION_BUILD_DATE="${BUILD_DATE}") -message("BUILD MACHINE: ${BUILD_MACHINE}") -zephyr_compile_options(-DVERSION_BUILD_MACHINE="${BUILD_MACHINE}") -message("BUILD_INFO: ${BUILD_INFO}") -zephyr_compile_options(-DVERSION_BUILD_INFO="${BUILD_INFO}") - -# Determine the ISA of the target and set appropriately -if (DEFINED CONFIG_ISA_THUMB2) - set(TARGET_ISA THUMB) -elseif (DEFINED CONFIG_ISA_ARM) - set(TARGET_ISA ARM) -elseif (DEFINED CONFIG_X86) - set(TARGET_ISA X86_32) -elseif (DEFINED CONFIG_XTENSA) - set(TARGET_ISA XTENSA) -elseif (DEFINED CONFIG_RISCV) - set(TARGET_ISA RISCV32) -elseif (DEFINED CONFIG_ARCH_POSIX) - set(TARGET_ISA X86_32) -else () - message(FATAL_ERROR "Unsupported ISA: ${CONFIG_ARCH}") -endif () -message("TARGET ISA: ${TARGET_ISA}") - -add_compile_options(-O0 -Wno-unknown-attributes) - -# WAMR Options -set(WAMR_BUILD_PLATFORM "zephyr") -set(WAMR_BUILD_TARGET ${TARGET_ISA}) -set(WAMR_BUILD_INTERP 1) -set(WAMR_BUILD_FAST_INTERP 0) -set(WAMR_BUILD_AOT 0) -set(WAMR_BUILD_JIT 0) -set(WAMR_BUILD_LIBC_BUILTIN 0) -set(WAMR_BUILD_LIBC_WASI 1) -set(WAMR_BUILD_LIB_PTHREAD 1) -set(WAMR_BUILD_REF_TYPES 1) -set(WASM_ENABLE_LOG 1) -set (WAMR_BUILD_SHARED_HEAP 1) - -if(NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_POOL) - set(WAMR_BUILD_GLOBAL_HEAP_POOL 1) -endif() -if(NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_SIZE) - set(WAMR_BUILD_GLOBAL_HEAP_SIZE 32767) -endif() - -set(WAMR_ROOT_DIR ${OCRE_ROOT_DIR}/wasm-micro-runtime) -include(${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) - -zephyr_include_directories( - ${OCRE_ROOT_DIR}/src/ - ${OCRE_ROOT_DIR}/src/ocre - ${OCRE_ROOT_DIR}/src/shared/platform -) - -set(component_sources - # Component support - ${OCRE_ROOT_DIR}/src/ocre/component/component.c - - # Components - ${OCRE_ROOT_DIR}/src/ocre/ocre_container_runtime/ocre_container_runtime.c - ${OCRE_ROOT_DIR}/src/ocre/components/container_supervisor/cs_main.c - ${OCRE_ROOT_DIR}/src/ocre/components/container_supervisor/cs_sm.c - ${OCRE_ROOT_DIR}/src/ocre/components/container_supervisor/cs_sm_impl.c -) - -# Collect all sources in one list -set(lib_sources - # Libraries - ${OCRE_ROOT_DIR}/src/ocre/sm/sm.c - ${OCRE_ROOT_DIR}/src/ocre/shell/ocre_shell.c - # Platform - ${OCRE_ROOT_DIR}/src/shared/platform/zephyr/core_fs.c - ${OCRE_ROOT_DIR}/src/shared/platform/zephyr/core_thread.c - ${OCRE_ROOT_DIR}/src/shared/platform/zephyr/core_mutex.c - ${OCRE_ROOT_DIR}/src/shared/platform/zephyr/core_mq.c - ${OCRE_ROOT_DIR}/src/shared/platform/zephyr/core_eventq.c - ${OCRE_ROOT_DIR}/src/shared/platform/zephyr/core_misc.c - ${OCRE_ROOT_DIR}/src/shared/platform/zephyr/core_memory.c - ${OCRE_ROOT_DIR}/src/shared/platform/zephyr/core_timer.c - - # Ocre APIs - ${OCRE_ROOT_DIR}/src/ocre/api/ocre_api.c - ${OCRE_ROOT_DIR}/src/ocre/api/ocre_common.c -) - -# Conditionally add sources -if(CONFIG_OCRE_TIMER) - list(APPEND lib_sources ${OCRE_ROOT_DIR}/src/ocre/ocre_timers/ocre_timer.c) -endif() - -if(CONFIG_OCRE_SENSORS) - list(APPEND lib_sources ${OCRE_ROOT_DIR}/src/ocre/ocre_sensors/ocre_sensors.c) -endif() - -if(CONFIG_RNG_SENSOR) - list(APPEND lib_sources ${OCRE_ROOT_DIR}/src/ocre/ocre_sensors/rng_sensor.c) -endif() - -if(DEFINED CONFIG_OCRE_GPIO) - list(APPEND lib_sources ${OCRE_ROOT_DIR}/src/ocre/ocre_gpio/ocre_gpio.c) -endif() - -if(CONFIG_OCRE_CONTAINER_MESSAGING) - list(APPEND lib_sources ${OCRE_ROOT_DIR}/src/ocre/ocre_messaging/ocre_messaging.c) -endif() - -# Add all sources to the app target at once -target_sources(app PRIVATE - ${WAMR_RUNTIME_LIB_SOURCE} - ${lib_sources} - ${component_sources} - ${OCRE_ROOT_DIR}/src/samples-mini/zephyr/main.c -) - -add_dependencies(app generate_messages) - -if(NOT "${OCRE_INPUT_FILE}" STREQUAL "") - add_dependencies(app generate_ocre_file) -endif() diff --git a/src/shell/CMakeLists.txt b/src/shell/CMakeLists.txt new file mode 100644 index 00000000..7e282934 --- /dev/null +++ b/src/shell/CMakeLists.txt @@ -0,0 +1,37 @@ +cmake_minimum_required(VERSION 3.20.0) + +add_library(OcreShell) + +target_sources(OcreShell + PRIVATE + shell.c + image.c + image/ls.c + image/pull.c + image/rm.c + container.c + container/create.c + container/inspect.c + container/kill.c + container/ps.c + container/rm.c + container/start.c + container/stop.c + container/wait.c + sha256/sha256.c +) + +target_include_directories(OcreShell + PUBLIC + include +) + +# target_link_libraries(OcreShell +# PUBLIC +# zephyr_interface +# ) + +# target_link_libraries(ocre +# PRIVATE +# -lpthread +# ) diff --git a/src/shell/command.h b/src/shell/command.h new file mode 100644 index 00000000..f4a75dae --- /dev/null +++ b/src/shell/command.h @@ -0,0 +1,6 @@ +#include + +struct ocre_command { + char *name; + int (*func)(struct ocre_context *ctx, char *argv0, int argc, char **argv); +}; diff --git a/src/shell/container.c b/src/shell/container.c new file mode 100644 index 00000000..a392e231 --- /dev/null +++ b/src/shell/container.c @@ -0,0 +1,68 @@ +#include +#include + +#include + +#include "command.h" + +#include "container/start.h" +#include "container/stop.h" +#include "container/rm.h" +#include "container/kill.h" +#include "container/inspect.h" +#include "container/wait.h" +#include "container/ps.h" +#include "container/create.h" + +static int print_usage(struct ocre_context *ctx, char *argv0, int argc, char **argv) +{ + fprintf(stderr, "Usage: %s container \n", argv0); + + fprintf(stderr, "\nCommands:\n"); + fprintf(stderr, " run Created and starts a new container\n"); + fprintf(stderr, " create Create a new container\n"); + fprintf(stderr, " start Start a container\n"); + fprintf(stderr, " stop Stop a running or paused container\n"); + fprintf(stderr, " kill Kill a running or paused container\n"); + // fprintf(stderr, " restart Restart a running, stopped, or paused container\n"); + // fprintf(stderr, " pause Pause a running container\n"); + // fprintf(stderr, " unpause Resume a paused container\n"); + fprintf(stderr, " inspect Display detailed information about a container\n"); + fprintf(stderr, " wait Wait for a container to exit\n"); + fprintf(stderr, " ps List containers\n"); + fprintf(stderr, " rm Remove a stopped container\n"); + return 0; +} + +static const struct ocre_command commands[] = { + {"help", print_usage}, + {"run", cmd_container_create_run}, + {"create", cmd_container_create_run}, + {"start", cmd_container_start}, + {"stop", cmd_container_stop}, + {"kill", cmd_container_kill}, + // {"restart", cmd_container_restart}, + // {"pause", cmd_container_pause}, + // {"unpause", cmd_container_unpause}, + {"inspect", cmd_container_inspect}, + {"wait", cmd_container_wait}, + {"ps", cmd_container_ps}, + {"rm", cmd_container_rm}, +}; + +int cmd_container(struct ocre_context *ctx, char *argv0, int argc, char **argv) +{ + if (argc < 2) { + return print_usage(ctx, argv0, argc, argv); + } + + for (size_t i = 0; i < sizeof(commands) / sizeof(commands[0]); i++) { + if (!strcmp(argv[1], commands[i].name)) { + return commands[i].func(ctx, argv0, argc - 1, &argv[1]); + } + } + + fprintf(stderr, "Invalid command: '%s container %s'\n\n", argv0, argv[1]); + + return print_usage(ctx, argv0, argc, argv); +} diff --git a/src/shell/container.h b/src/shell/container.h new file mode 100644 index 00000000..94058a5d --- /dev/null +++ b/src/shell/container.h @@ -0,0 +1,3 @@ +#include + +int cmd_container(struct ocre_context *ctx, char *argv0, int argc, char **argv); diff --git a/src/shell/container/create.c b/src/shell/container/create.c new file mode 100644 index 00000000..91bf4aec --- /dev/null +++ b/src/shell/container/create.c @@ -0,0 +1,153 @@ +#include +#include +#include +#include +#include + +#include + +#include "../command.h" + +static int usage(const char *argv0, char *cmd) +{ + fprintf(stderr, "Usage: %s container %s [options] IMAGE [ARG...]\n", argv0, cmd); + if (!strcmp(cmd, "create")) { + fprintf(stderr, "\nCreates a container in the Ocre context.\n"); + } else if (!strcmp(cmd, "run")) { + fprintf(stderr, "\nCreates and starts a container in the Ocre context.\n"); + } + fprintf(stderr, "\nOptions:\n"); + fprintf(stderr, " -d Creates a detached container\n"); + fprintf(stderr, " -n CONTAINER_ID Specifies a container ID\n"); + fprintf(stderr, " -r RUNTIME Specifies the runtime to use\n"); + fprintf(stderr, " -v VOLUME:MOUNTPOINT Adds a volume to be mounted into the container\n"); + fprintf(stderr, " -v /ABSPATH:MOUNTPOINT Adds a directory to be mounted into the container\n"); + fprintf(stderr, " -k CAPABILITY Adds a capability to the container\n"); + fprintf(stderr, " -e VAR=VALUE Sets an environment variable in the container\n"); + fprintf(stderr, "\nOptions '-v' and '-e' and '-k' can be supplied multiple times.\n"); + + return -1; +} + +int cmd_container_create_run(struct ocre_context *ctx, char *argv0, int argc, char **argv) +{ + int ret = -1; + + if (argc < 2) { + fprintf(stderr, "'%s container %s' requires arguments\n\n", argv0, argv[0]); + return usage(argv0, argv[0]); + } + + bool detached = false; + char *runtime = NULL; + char *container_id = NULL; + const char **capabilities = NULL; + const char **environment = NULL; + + size_t capabilities_count = 0; + size_t environment_count = 0; + + opterr = 0; + + int opt; + while ((opt = getopt(argc, argv, "de:k:n:r:v:")) != -1) { + switch (opt) { + case 'd': { + if (detached) { + fprintf(stderr, "Detached mode can be set only once\n\n"); + usage(argv0, argv[0]); + goto cleanup; + } + + detached = true; + continue; + } + case 'n': { + if (container_id) { + fprintf(stderr, "Container ID can be set only once\n\n"); + usage(argv0, argv[0]); + goto cleanup; + } + + container_id = optarg; + continue; + } + case 'r': { + if (runtime) { + fprintf(stderr, "Runtime can be set only once\n\n"); + usage(argv0, argv[0]); + goto cleanup; + } + + runtime = optarg; + continue; + } + case 'v': { + fprintf(stderr, "Volume '%s' will be mounted\n", optarg); + continue; + } + case 'k': { + capabilities = realloc(capabilities, sizeof(char *) * (capabilities_count + 1)); + capabilities[capabilities_count++] = optarg; + continue; + } + case 'e': { + environment = realloc(environment, sizeof(char *) * (environment_count + 1)); + environment[environment_count++] = optarg; + continue; + } + case '?': { + fprintf(stderr, "Invalid option '-%c'\n", optopt); + goto cleanup; + break; + } + } + } + + environment = realloc(environment, sizeof(char *) * (environment_count + 1)); + environment[environment_count++] = NULL; + + capabilities = realloc(capabilities, sizeof(char *) * (capabilities_count + 1)); + capabilities[capabilities_count++] = NULL; + + if (optind >= argc) { + fprintf(stderr, "'%s container %s' requires at least one non option argument\n\n", argv0, argv[0]); + return usage(argv0, argv[0]); + goto cleanup; + } + + const struct ocre_container_args arguments = { + .argv = (const char **)&argv[optind + 1], + .capabilities = capabilities, + .envp = environment, + }; + + struct ocre_container *container = + ocre_context_create_container(ctx, argv[optind], runtime, container_id, detached, &arguments); + + if (!container) { + fprintf(stderr, "Failed to create container\n"); + goto cleanup; + } + + if (!strcmp(argv[0], "run")) { + if (ocre_container_start(container)) { + fprintf(stderr, "Failed to start container\n"); + goto cleanup; + } + } + + if (detached) { + char *cid = ocre_container_get_id_a(container); + fprintf(stdout, "%s\n", cid); + free(cid); + } + + ret = 0; + +cleanup: + free(capabilities); + free(environment); + + return ret; +} diff --git a/src/shell/container/create.h b/src/shell/container/create.h new file mode 100644 index 00000000..5822c1ce --- /dev/null +++ b/src/shell/container/create.h @@ -0,0 +1,3 @@ +#include + +int cmd_container_create_run(struct ocre_context *ctx, char *argv0, int argc, char **argv); diff --git a/src/shell/container/inspect.c b/src/shell/container/inspect.c new file mode 100644 index 00000000..6f3f6c7a --- /dev/null +++ b/src/shell/container/inspect.c @@ -0,0 +1,25 @@ +#include +#include + +#include + +#include "../command.h" + +static int usage(const char *argv0) +{ + fprintf(stderr, "Usage: %s container status CONTAINER\n", argv0); + fprintf(stderr, "\nChecks the status of a container in the OCRE context.\n"); + return -1; +} + +int cmd_container_inspect(struct ocre_context *ctx, char *argv0, int argc, char **argv) +{ + if (argc == 1) { + printf("Getting status of container '%s'...\n", argv[1]); + } else { + fprintf(stderr, "'%s container status' requires exactly one argument\n\n", argv0); + return usage(argv0); + } + + return 0; +} diff --git a/src/shell/container/inspect.h b/src/shell/container/inspect.h new file mode 100644 index 00000000..2b7cf92e --- /dev/null +++ b/src/shell/container/inspect.h @@ -0,0 +1,3 @@ +#include + +int cmd_container_inspect(struct ocre_context *ctx, char *argv0, int argc, char **argv); diff --git a/src/shell/container/kill.c b/src/shell/container/kill.c new file mode 100644 index 00000000..602b6922 --- /dev/null +++ b/src/shell/container/kill.c @@ -0,0 +1,36 @@ +#include +#include + +#include + +#include "../command.h" + +static int usage(const char *argv0) +{ + fprintf(stderr, "Usage: %s container kill CONTAINER\n", argv0); + fprintf(stderr, "\nKills a container in the OCRE context.\n"); + return -1; +} + +int cmd_container_kill(struct ocre_context *ctx, char *argv0, int argc, char **argv) +{ + if (argc == 2) { + struct ocre_container *container = ocre_context_get_container_by_id(ctx, argv[1]); + if (!container) { + fprintf(stderr, "Failed to get container '%s'\n", argv[1]); + return -1; + } + + if (ocre_container_get_status(container) != OCRE_CONTAINER_STATUS_RUNNING) { + fprintf(stderr, "Container '%s' is not running\n", argv[1]); + return -1; + } + + return ocre_container_kill(container); + } else { + fprintf(stderr, "'%s container kill' requires exactly one argument\n\n", argv0); + return usage(argv0); + } + + return 0; +} diff --git a/src/shell/container/kill.h b/src/shell/container/kill.h new file mode 100644 index 00000000..f239e6d0 --- /dev/null +++ b/src/shell/container/kill.h @@ -0,0 +1,3 @@ +#include + +int cmd_container_kill(struct ocre_context *ctx, char *argv0, int argc, char **argv); diff --git a/src/shell/container/ps.c b/src/shell/container/ps.c new file mode 100644 index 00000000..40a73086 --- /dev/null +++ b/src/shell/container/ps.c @@ -0,0 +1,113 @@ +#include +#include +#include + +#include + +#include "../command.h" + +static const char *container_statuses[] = { + "UNKNOWN", + "CREATED", + "RUNNING", + "PAUSED ", + "EXITED ", + "STOPPED", + "ERROR " +}; + +static int usage(const char *argv0) +{ + fprintf(stderr, "Usage: %s container ps [CONTAINER]\n", argv0); + fprintf(stderr, "\nList containers in OCRE context.\n"); + return -1; +} + +static void header(void) +{ + printf("ID\tSTATUS\tIMAGE\n"); +} + +static int list_container(struct ocre_container *container) +{ + int ret = -1; + char *id = ocre_container_get_id_a(container); + char *image = ocre_container_get_image_a(container); + ocre_container_status_t status = ocre_container_get_status(container); + + if (!id || !image || status == OCRE_CONTAINER_STATUS_UNKNOWN) { + goto finish; + } + + printf("%s\t%s\t%s\n", id, container_statuses[status], image); + + ret = 0; + +finish: + free(id); + free(image); + + return ret; +} + +static int list_containers(struct ocre_context *ctx) +{ + int ret = -1; + int num_containers = ocre_context_get_num_containers(ctx); + if (num_containers < 0) { + fprintf(stderr, "Failed to get number of containers\n"); + return -1; + } + + if (num_containers == 0) { + return 0; + } + + struct ocre_container **containers = malloc(sizeof(struct ocre_container *) * num_containers); + if (!containers) { + fprintf(stderr, "Failed to allocate memory for containers\n"); + return -1; + } + + num_containers = ocre_context_list_containers(ctx, containers, num_containers); + if (num_containers < 0) { + fprintf(stderr, "Failed to list containers\n"); + goto finish; + } + + for (int i = 0; i < num_containers; i++) { + if (list_container(containers[i])) { + fprintf(stderr, "Failed to list container %d\n", i); + goto finish; + } + } + + ret = 0; + +finish: + free(containers); + return ret; +} + +int cmd_container_ps(struct ocre_context *ctx, char *argv0, int argc, char **argv) +{ + switch (argc) { + case 1: { + header(); + return list_containers(ctx); + } + case 2: { + struct ocre_container *container = ocre_context_get_container_by_id(ctx, argv[1]); + if (!container) { + fprintf(stderr, "Failed to get container '%s'\n", argv[1]); + return -1; + } + + header(); + return list_container(container); + } + default: + fprintf(stderr, "'%s container ps' requires at most one argument\n\n", argv0); + return usage(argv0); + } +} diff --git a/src/shell/container/ps.h b/src/shell/container/ps.h new file mode 100644 index 00000000..7e44a77b --- /dev/null +++ b/src/shell/container/ps.h @@ -0,0 +1,3 @@ +#include + +int cmd_container_ps(struct ocre_context *ctx, char *argv0, int argc, char **argv); diff --git a/src/shell/container/rm.c b/src/shell/container/rm.c new file mode 100644 index 00000000..7005783a --- /dev/null +++ b/src/shell/container/rm.c @@ -0,0 +1,36 @@ +#include +#include + +#include "../command.h" +#include "ocre/ocre.h" + +static int usage(const char *argv0) +{ + fprintf(stderr, "Usage: %s container rm CONTAINER\n", argv0); + fprintf(stderr, "\nRemoves a stopped container from the OCRE context.\n"); + return -1; +} + +int cmd_container_rm(struct ocre_context *ctx, char *argv0, int argc, char **argv) +{ + if (argc == 2) { + struct ocre_container *container = ocre_context_get_container_by_id(ctx, argv[1]); + if (!container) { + fprintf(stderr, "Failed to get container '%s'\n", argv[1]); + return -1; + } + + ocre_container_status_t status = ocre_container_get_status(container); + if (status != OCRE_CONTAINER_STATUS_STOPPED && status != OCRE_CONTAINER_STATUS_CREATED) { + fprintf(stderr, "Container '%s' is in use\n", argv[1]); + return -1; + } + + return ocre_context_remove_container(ctx, container); + } else { + fprintf(stderr, "'%s container rm' requires exactly one argument\n\n", argv0); + return usage(argv0); + } + + return 0; +} diff --git a/src/shell/container/rm.h b/src/shell/container/rm.h new file mode 100644 index 00000000..49650208 --- /dev/null +++ b/src/shell/container/rm.h @@ -0,0 +1,3 @@ +#include + +int cmd_container_rm(struct ocre_context *ctx, char *argv0, int argc, char **argv); diff --git a/src/shell/container/start.c b/src/shell/container/start.c new file mode 100644 index 00000000..6e3cdd99 --- /dev/null +++ b/src/shell/container/start.c @@ -0,0 +1,37 @@ +#include +#include + +#include + +#include "../command.h" + +static int usage(const char *argv0) +{ + fprintf(stderr, "Usage: %s container start CONTAINER\n", argv0); + fprintf(stderr, "\nStarts a container in the OCRE context.\n"); + return -1; +} + +int cmd_container_start(struct ocre_context *ctx, char *argv0, int argc, char **argv) +{ + if (argc == 2) { + struct ocre_container *container = ocre_context_get_container_by_id(ctx, argv[1]); + if (!container) { + fprintf(stderr, "Failed to get container '%s'\n", argv[1]); + return -1; + } + + ocre_container_status_t status = ocre_container_get_status(container); + if (status != OCRE_CONTAINER_STATUS_CREATED && status != OCRE_CONTAINER_STATUS_STOPPED) { + fprintf(stderr, "Container '%s' is not ready to run\n", argv[1]); + return -1; + } + + return ocre_container_start(container); + } else { + fprintf(stderr, "'%s container start' requires exactly one argument\n\n", argv0); + return usage(argv0); + } + + return 0; +} diff --git a/src/shell/container/start.h b/src/shell/container/start.h new file mode 100644 index 00000000..fb4c1392 --- /dev/null +++ b/src/shell/container/start.h @@ -0,0 +1,3 @@ +#include + +int cmd_container_start(struct ocre_context *ctx, char *argv0, int argc, char **argv); diff --git a/src/shell/container/stop.c b/src/shell/container/stop.c new file mode 100644 index 00000000..5a2e758a --- /dev/null +++ b/src/shell/container/stop.c @@ -0,0 +1,25 @@ +#include +#include + +#include + +#include "../command.h" + +static int usage(const char *argv0) +{ + fprintf(stderr, "Usage: %s container stop CONTAINER\n", argv0); + fprintf(stderr, "\nStops a container in the OCRE context.\n"); + return -1; +} + +int cmd_container_stop(struct ocre_context *ctx, char *argv0, int argc, char **argv) +{ + if (argc == 1) { + printf("Stopping container '%s'...\n", argv[1]); + } else { + fprintf(stderr, "'%s container stop' requires exactly one argument\n\n", argv0); + return usage(argv0); + } + + return 0; +} diff --git a/src/shell/container/stop.h b/src/shell/container/stop.h new file mode 100644 index 00000000..5c0837e5 --- /dev/null +++ b/src/shell/container/stop.h @@ -0,0 +1,3 @@ +#include + +int cmd_container_stop(struct ocre_context *ctx, char *argv0, int argc, char **argv); diff --git a/src/shell/container/wait.c b/src/shell/container/wait.c new file mode 100644 index 00000000..dba65cc4 --- /dev/null +++ b/src/shell/container/wait.c @@ -0,0 +1,44 @@ +#include +#include + +#include + +#include "../command.h" + +static int usage(const char *argv0) +{ + fprintf(stderr, "Usage: %s container wait CONTAINER\n", argv0); + fprintf(stderr, "\nWaits for a container to exit.\n"); + return -1; +} + +int cmd_container_wait(struct ocre_context *ctx, char *argv0, int argc, char **argv) +{ + if (argc == 2) { + struct ocre_container *container = ocre_context_get_container_by_id(ctx, argv[1]); + if (!container) { + fprintf(stderr, "Failed to get container '%s'\n", argv[1]); + return -1; + } + + ocre_container_status_t status = ocre_container_get_status(container); + if (status == OCRE_CONTAINER_STATUS_UNKNOWN || status == OCRE_CONTAINER_STATUS_CREATED) { + fprintf(stderr, "Container '%s' has not started\n", argv[1]); + return -1; + } + + int return_code; + int rc = ocre_container_wait(container, &return_code); + if (rc) { + fprintf(stderr, "Failed to wait for container '%s'\n", argv[1]); + return -1; + } + + return return_code; + } else { + fprintf(stderr, "'%s container wait' requires exactly one argument\n\n", argv0); + return usage(argv0); + } + + return 0; +} diff --git a/src/shell/container/wait.h b/src/shell/container/wait.h new file mode 100644 index 00000000..dcd05370 --- /dev/null +++ b/src/shell/container/wait.h @@ -0,0 +1,3 @@ +#include + +int cmd_container_wait(struct ocre_context *ctx, char *argv0, int argc, char **argv); diff --git a/src/shell/image.c b/src/shell/image.c new file mode 100644 index 00000000..6e81da21 --- /dev/null +++ b/src/shell/image.c @@ -0,0 +1,43 @@ +#include +#include + +#include "command.h" + +#include "image/ls.h" +#include "image/rm.h" +#include "image/pull.h" + +static int print_usage(struct ocre_context *ctx, char *argv0, int argc, char **argv) +{ + fprintf(stderr, "Usage: %s image \n", argv0); + + fprintf(stderr, "\nCommands:\n"); + fprintf(stderr, " ls List images\n"); + fprintf(stderr, " pull Pull an image\n"); + fprintf(stderr, " rm Remove an image\n"); + return -1; +} + +static const struct ocre_command commands[] = { + {"help", print_usage}, + {"ls", cmd_image_ls}, + {"pull", cmd_image_pull}, + {"rm", cmd_image_rm}, +}; + +int cmd_image(struct ocre_context *ctx, char *argv0, int argc, char **argv) +{ + if (argc < 2) { + return print_usage(ctx, argv0, argc, argv); + } + + for (size_t i = 0; i < sizeof(commands) / sizeof(commands[0]); i++) { + if (!strcmp(argv[1], commands[i].name)) { + return commands[i].func(ctx, argv0, argc - 1, &argv[1]); + } + } + + fprintf(stderr, "Invalid command: '%s image %s'\n\n", argv0, argv[1]); + + return print_usage(ctx, argv0, argc, argv); +} diff --git a/src/shell/image.h b/src/shell/image.h new file mode 100644 index 00000000..31c4ac49 --- /dev/null +++ b/src/shell/image.h @@ -0,0 +1,3 @@ +#include + +int cmd_image(struct ocre_context *ctx, char *argv0, int argc, char **argv); diff --git a/src/shell/image/ls.c b/src/shell/image/ls.c new file mode 100644 index 00000000..6c70f4f3 --- /dev/null +++ b/src/shell/image/ls.c @@ -0,0 +1,202 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "../command.h" +#include "../sha256/sha256.h" + +#define FILE_BUFFER_SIZE 1024 + +static int sha256_file(const char *path, char *hash) +{ + int ret = -1; + void *buffer = NULL; + + if (!path || !hash) { + return -1; + } + + int fd = open(path, O_RDONLY); + if (fd < 0) { + return -1; + } + + struct stat finfo; + int rc = fstat(fd, &finfo); + if (rc < 0) { + goto finish; + } + + off_t file_size = finfo.st_size; + + if (!file_size) { + goto finish; + } + + buffer = malloc(FILE_BUFFER_SIZE); + if (!buffer) { + goto finish; + } + + struct sha256_buff buff; + sha256_init(&buff); + + off_t total_bytes_read = 0; + while (total_bytes_read < file_size) { + ssize_t bytes_read = read(fd, buffer, FILE_BUFFER_SIZE); + if (bytes_read < 0) { + goto finish; + } + + if (!bytes_read) { + ret = 0; + break; + } + + sha256_update(&buff, buffer, bytes_read); + + total_bytes_read += bytes_read; + } + + sha256_finalize(&buff); + sha256_read_hex(&buff, hash); + +finish: + free(buffer); + close(fd); + + return ret; +} + +static int usage(const char *argv0) +{ + fprintf(stderr, "Usage: %s image ls [IMAGE]\n", argv0); + fprintf(stderr, "\nList images in local storage.\n"); + return -1; +} + +static void header() +{ + printf("SHA-256\t\t\t\t\t\t\t\t\tSIZE\tNAME\n"); +} + +static int list_image(const char *name, const char *path) +{ + if (!path) { + fprintf(stderr, "Invalid image path\n"); + return -1; + } + + struct stat st; + stat(path, &st); + + if (S_ISREG(st.st_mode)) { + char hash[65] = {0}; /* hash[64] is null-byte */ + + sha256_file(path, hash); + + printf("%s\t%jd\t%s\n", hash, (intmax_t)st.st_size, name); + } + + return 0; +} + +static int list_images(const char *path) +{ + int ret = 0; + DIR *d; + struct dirent *dir; + + d = opendir(path); + if (!d) { + fprintf(stderr, "Failed to open directory '%s'\n", path); + return -1; + } + + while ((dir = readdir(d)) != NULL) { + char *image_path = malloc(strlen(path) + strlen(dir->d_name) + 2); + if (!image_path) { + fprintf(stderr, "Failed to allocate memory for image path\n"); + ret = -1; + break; + } + + strcpy(image_path, path); + strcat(image_path, "/"); + strcat(image_path, dir->d_name); + + if (list_image(dir->d_name, image_path)) { + fprintf(stderr, "Failed to list image '%s'\n", image_path); + ret = -1; + } + + free(image_path); + } + + closedir(d); + + return ret; +} + +int cmd_image_ls(struct ocre_context *ctx, char *argv0, int argc, char **argv) +{ + switch (argc) { + case 1: { + char *working_directory = ocre_context_get_working_directory(ctx); + + char *image_dir = malloc(strlen(working_directory) + strlen("/images") + 1); + if (!image_dir) { + fprintf(stderr, "Failed to allocate memory for image directory path\n"); + return -1; + } + + strcpy(image_dir, working_directory); + strcat(image_dir, "/images"); + + header(); + + if (list_images(image_dir)) { + fprintf(stderr, "Failed to list images in directory '%s'\n", image_dir); + } + + free(image_dir); + + break; + } + case 2: { + char *working_directory = ocre_context_get_working_directory(ctx); + + char *image_path = malloc(strlen(working_directory) + strlen("/images") + strlen(argv[1]) + 2); + if (!image_path) { + fprintf(stderr, "Failed to allocate memory for image path\n"); + return -1; + } + + strcpy(image_path, working_directory); + strcat(image_path, "/images/"); + strcat(image_path, argv[1]); + + header(); + + if (list_image(argv[1], image_path)) { + fprintf(stderr, "Failed to list image '%s'\n", image_path); + } + + free(image_path); + + break; + } + default: { + fprintf(stderr, "'%s image ls' requires at most one argument\n\n", argv0); + return usage(argv0); + } + } + + return 0; +} diff --git a/src/shell/image/ls.h b/src/shell/image/ls.h new file mode 100644 index 00000000..a70b70ae --- /dev/null +++ b/src/shell/image/ls.h @@ -0,0 +1,3 @@ +#include + +int cmd_image_ls(struct ocre_context *ctx, char *argv0, int argc, char **argv); diff --git a/src/shell/image/pull.c b/src/shell/image/pull.c new file mode 100644 index 00000000..b258bd00 --- /dev/null +++ b/src/shell/image/pull.c @@ -0,0 +1,29 @@ +#include +#include + +#include + +#include "../command.h" + +static int usage(const char *argv0) +{ + fprintf(stderr, "Usage: %s image pull URL\n", argv0); // TODO: NAME[:TAG|@DIGEST] + fprintf(stderr, "\nDownloads an image from a remote repository to the local storage.\n"); + return -1; +} + +int cmd_image_pull(struct ocre_context *ctx, char *argv0, int argc, char **argv) +{ + if (argc < 1) { + fprintf(stderr, "'%s image pull' requires at least one argument\n\n", argv0); + return usage(argv0); + } + + if (argc == 1) { + printf("Pulling image '%s'...\n", argv[1]); + } else { + printf("Pulling image '%s' and saving locally as '%s'...\n", argv[1], argv[2]); + } + + return 0; +} diff --git a/src/shell/image/pull.h b/src/shell/image/pull.h new file mode 100644 index 00000000..e5451a4d --- /dev/null +++ b/src/shell/image/pull.h @@ -0,0 +1,3 @@ +#include + +int cmd_image_pull(struct ocre_context *ctx, char *argv0, int argc, char **argv); diff --git a/src/shell/image/rm.c b/src/shell/image/rm.c new file mode 100644 index 00000000..8625db25 --- /dev/null +++ b/src/shell/image/rm.c @@ -0,0 +1,44 @@ +#include +#include +#include + +#include + +#include "../command.h" + +static int usage(const char *argv0) +{ + fprintf(stderr, "Usage: %s image rm \n", argv0); + fprintf(stderr, "\nRemoves an image from local storage.\n"); + return -1; +} + +int cmd_image_rm(struct ocre_context *ctx, char *argv0, int argc, char **argv) +{ + if (argc == 2) { + char *working_directory = ocre_context_get_working_directory(ctx); + + char *image_path = malloc(strlen(working_directory) + strlen("/images") + strlen(argv[1]) + 2); + if (!image_path) { + fprintf(stderr, "Failed to allocate memory for image path\n"); + return -1; + } + + strcpy(image_path, working_directory); + strcat(image_path, "/images/"); + strcat(image_path, argv[1]); + + /* Danger: we do not check if the image is in use */ + + if (remove(image_path)) { + fprintf(stderr, "Failed to remove image '%s'\n", image_path); + } + + free(image_path); + } else { + fprintf(stderr, "'%s image rm' requires exactly one argument\n\n", argv0); + return usage(argv0); + } + + return 0; +} diff --git a/src/shell/image/rm.h b/src/shell/image/rm.h new file mode 100644 index 00000000..5c61d6b6 --- /dev/null +++ b/src/shell/image/rm.h @@ -0,0 +1,3 @@ +#include + +int cmd_image_rm(struct ocre_context *ctx, char *argv0, int argc, char **argv); diff --git a/src/shell/include/ocre/shell/shell.h b/src/shell/include/ocre/shell/shell.h new file mode 100644 index 00000000..33fb42a3 --- /dev/null +++ b/src/shell/include/ocre/shell/shell.h @@ -0,0 +1,3 @@ +#include // for context + +int ocre_shell(struct ocre_context *ctx, int argc, char *argv[]); diff --git a/src/shell/sha256/LICENSE b/src/shell/sha256/LICENSE new file mode 100644 index 00000000..8534e7b3 --- /dev/null +++ b/src/shell/sha256/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 LekKit + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/shell/sha256/sha256.c b/src/shell/sha256/sha256.c new file mode 100644 index 00000000..9fef5925 --- /dev/null +++ b/src/shell/sha256/sha256.c @@ -0,0 +1,182 @@ +/* + MIT License + + Copyright (c) 2020 LekKit https://github.com/LekKit + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +/* Details of the implementation, etc can be found here: https://en.wikipedia.org/wiki/SHA-2 + See sha256.h for short documentation on library usage */ + +#include "sha256.h" + +void sha256_init(struct sha256_buff* buff) { + buff->h[0] = 0x6a09e667; + buff->h[1] = 0xbb67ae85; + buff->h[2] = 0x3c6ef372; + buff->h[3] = 0xa54ff53a; + buff->h[4] = 0x510e527f; + buff->h[5] = 0x9b05688c; + buff->h[6] = 0x1f83d9ab; + buff->h[7] = 0x5be0cd19; + buff->data_size = 0; + buff->chunk_size = 0; +} + +static const uint32_t k[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +#define rotate_r(val, bits) (val >> bits | val << (32 - bits)) + +static void sha256_calc_chunk(struct sha256_buff* buff, const uint8_t* chunk) { + uint32_t w[64]; + uint32_t tv[8]; + uint32_t i; + + for (i=0; i<16; ++i){ + w[i] = (uint32_t) chunk[0] << 24 | (uint32_t) chunk[1] << 16 | (uint32_t) chunk[2] << 8 | (uint32_t) chunk[3]; + chunk += 4; + } + + for (i=16; i<64; ++i){ + uint32_t s0 = rotate_r(w[i-15], 7) ^ rotate_r(w[i-15], 18) ^ (w[i-15] >> 3); + uint32_t s1 = rotate_r(w[i-2], 17) ^ rotate_r(w[i-2], 19) ^ (w[i-2] >> 10); + w[i] = w[i-16] + s0 + w[i-7] + s1; + } + + for (i = 0; i < 8; ++i) + tv[i] = buff->h[i]; + + for (i=0; i<64; ++i){ + uint32_t S1 = rotate_r(tv[4], 6) ^ rotate_r(tv[4], 11) ^ rotate_r(tv[4], 25); + uint32_t ch = (tv[4] & tv[5]) ^ (~tv[4] & tv[6]); + uint32_t temp1 = tv[7] + S1 + ch + k[i] + w[i]; + uint32_t S0 = rotate_r(tv[0], 2) ^ rotate_r(tv[0], 13) ^ rotate_r(tv[0], 22); + uint32_t maj = (tv[0] & tv[1]) ^ (tv[0] & tv[2]) ^ (tv[1] & tv[2]); + uint32_t temp2 = S0 + maj; + + tv[7] = tv[6]; + tv[6] = tv[5]; + tv[5] = tv[4]; + tv[4] = tv[3] + temp1; + tv[3] = tv[2]; + tv[2] = tv[1]; + tv[1] = tv[0]; + tv[0] = temp1 + temp2; + } + + for (i = 0; i < 8; ++i) + buff->h[i] += tv[i]; +} + +void sha256_update(struct sha256_buff* buff, const void* data, size_t size) { + const uint8_t* ptr = (const uint8_t*)data; + buff->data_size += size; + /* If there is data left in buff, concatenate it to process as new chunk */ + if (size + buff->chunk_size >= 64) { + uint8_t tmp_chunk[64]; + memcpy(tmp_chunk, buff->last_chunk, buff->chunk_size); + memcpy(tmp_chunk + buff->chunk_size, ptr, 64 - buff->chunk_size); + ptr += (64 - buff->chunk_size); + size -= (64 - buff->chunk_size); + buff->chunk_size = 0; + sha256_calc_chunk(buff, tmp_chunk); + } + /* Run over data chunks */ + while (size >= 64) { + sha256_calc_chunk(buff, ptr); + ptr += 64; + size -= 64; + } + + /* Save remaining data in buff, will be reused on next call or finalize */ + memcpy(buff->last_chunk + buff->chunk_size, ptr, size); + buff->chunk_size += size; +} + +void sha256_finalize(struct sha256_buff* buff) { + buff->last_chunk[buff->chunk_size] = 0x80; + buff->chunk_size++; + memset(buff->last_chunk + buff->chunk_size, 0, 64 - buff->chunk_size); + + /* If there isn't enough space to fit int64, pad chunk with zeroes and prepare next chunk */ + if (buff->chunk_size > 56) { + sha256_calc_chunk(buff, buff->last_chunk); + memset(buff->last_chunk, 0, 64); + } + + /* Add total size as big-endian int64 x8 */ + uint64_t size = buff->data_size * 8; + int i; + for (i = 8; i > 0; --i) { + buff->last_chunk[55+i] = size & 255; + size >>= 8; + } + + sha256_calc_chunk(buff, buff->last_chunk); +} + +void sha256_read(const struct sha256_buff* buff, uint8_t* hash) { + uint32_t i; + for (i = 0; i < 8; i++) { + hash[i*4] = (buff->h[i] >> 24) & 255; + hash[i*4 + 1] = (buff->h[i] >> 16) & 255; + hash[i*4 + 2] = (buff->h[i] >> 8) & 255; + hash[i*4 + 3] = buff->h[i] & 255; + } +} + +static void bin_to_hex(const void* data, uint32_t len, char* out) { + static const char* const lut = "0123456789abcdef"; + uint32_t i; + for (i = 0; i < len; ++i){ + uint8_t c = ((const uint8_t*)data)[i]; + out[i*2] = lut[c >> 4]; + out[i*2 + 1] = lut[c & 15]; + } +} + +void sha256_read_hex(const struct sha256_buff* buff, char* hex) { + uint8_t hash[32]; + sha256_read(buff, hash); + bin_to_hex(hash, 32, hex); +} + +void sha256_easy_hash(const void* data, size_t size, uint8_t* hash) { + struct sha256_buff buff; + sha256_init(&buff); + sha256_update(&buff, data, size); + sha256_finalize(&buff); + sha256_read(&buff, hash); +} + +void sha256_easy_hash_hex(const void* data, size_t size, char* hex) { + uint8_t hash[32]; + sha256_easy_hash(data, size, hash); + bin_to_hex(hash, 32, hex); +} diff --git a/src/shell/sha256/sha256.h b/src/shell/sha256/sha256.h new file mode 100644 index 00000000..a419b23e --- /dev/null +++ b/src/shell/sha256/sha256.h @@ -0,0 +1,99 @@ +/* + MIT License + + Copyright (c) 2020 LekKit https://github.com/LekKit + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#ifndef SHA256_H +#define SHA256_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +struct sha256_buff { + uint64_t data_size; + uint32_t h[8]; + uint8_t last_chunk[64]; + uint8_t chunk_size; +}; + +/* Initialization, must be called before any further use */ +void sha256_init(struct sha256_buff* buff); + +/* Process block of data of arbitary length, can be used on data streams (files, etc) */ +void sha256_update(struct sha256_buff* buff, const void* data, size_t size); + +/* Produces final hash values (digest) to be read + If the buffer is reused later, init must be called again */ +void sha256_finalize(struct sha256_buff* buff); + +/* Read digest into 32-byte binary array */ +void sha256_read(const struct sha256_buff* buff, uint8_t* hash); + +/* Read digest into 64-char string as hex (without null-byte) */ +void sha256_read_hex(const struct sha256_buff* buff, char* hex); + +/* Hashes single contiguous block of data and reads digest into 32-byte binary array */ +void sha256_easy_hash(const void* data, size_t size, uint8_t* hash); + +/* Hashes single contiguous block of data and reads digest into 64-char string (without null-byte) */ +void sha256_easy_hash_hex(const void* data, size_t size, char* hex); + +#ifdef __cplusplus +} + +#include + +class SHA256 { +private: + struct sha256_buff buff; +public: + SHA256() { + sha256_init(&buff); + } + + void update(const void* data, std::size_t size) { + sha256_update(&buff, data, size); + } + + std::string hash() { + char hash[64]; + sha256_finalize(&buff); + sha256_read_hex(&buff, hash); + sha256_init(&buff); + return std::string(hash, 64); + } + + static std::string hashString(const std::string& str) { + char hash[64]; + sha256_easy_hash_hex(str.c_str(), str.length(), hash); + return std::string(hash, 64); + } +}; + +#endif + +#endif diff --git a/src/shell/shell.c b/src/shell/shell.c new file mode 100644 index 00000000..ad6d77e3 --- /dev/null +++ b/src/shell/shell.c @@ -0,0 +1,92 @@ +#include +#include +#include + +#include // for context // maybe for api? + +#include "command.h" +#include "image.h" +#include "image/ls.h" +#include "image/pull.h" +#include "container.h" +#include "container/kill.h" +#include "container/ps.h" +#include "container/rm.h" +#include "container/start.h" +#include "container/inspect.h" +#include "container/stop.h" +#include "container/wait.h" +#include "container/create.h" + +static int print_version(struct ocre_context *ctx, char *argv0, int argc, char **argv) +{ + fprintf(stdout, "Ocre version 1.0\n"); + return 0; +} + +static int print_usage(struct ocre_context *ctx, char *argv0, int argc, char **argv) +{ + fprintf(stderr, "Usage: %s \n", argv0); + + fprintf(stderr, "\nCommands:\n"); + fprintf(stderr, " help Display this help message\n"); + fprintf(stderr, " version Display version information\n"); + fprintf(stderr, " image Image manipulation commands\n"); + fprintf(stderr, " container Container management commands\n"); + fprintf(stderr, "\nShortcut Commands:\n"); + fprintf(stderr, " ps container ps\n"); + fprintf(stderr, " create container create\n"); + fprintf(stderr, " run container run\n"); + fprintf(stderr, " start container start\n"); + fprintf(stderr, " stop container stop\n"); + fprintf(stderr, " kill container kill\n"); + // fprintf(stderr, " restart container restart\n"); + // fprintf(stderr, " pause container pause\n"); + // fprintf(stderr, " unpause container unpause\n"); + fprintf(stderr, " rm container rm\n"); + fprintf(stderr, " images image ls\n"); + fprintf(stderr, " pull image pull\n"); + return -1; +} + +static const struct ocre_command commands[] = { + // general commands + {"help", print_usage}, + {"version", print_version}, + {"image", cmd_image}, + {"container", cmd_container}, + // container shortcuts + {"ps", cmd_container_ps}, + {"create", cmd_container_create_run}, + {"run", cmd_container_create_run}, + {"start", cmd_container_start}, + {"stop", cmd_container_stop}, + {"kill", cmd_container_kill}, + {"rm", cmd_container_rm}, + // image shortcuts + {"images", cmd_image_ls}, + {"pull", cmd_image_pull}, +}; + +int ocre_shell(struct ocre_context *ctx, int argc, char *argv[]) +{ + if (argc < 2) { + return print_usage(ctx, argv[0], argc, argv); + } + + fprintf(stderr, "Using context: %p\n", ctx); + + optind = 1; + + for (size_t i = 0; i < sizeof(commands) / sizeof(commands[0]); i++) { + if (!strcmp(argv[1], commands[i].name)) { + return commands[i].func(ctx, argv[0], argc - 1, &argv[1]); + } + } + + fprintf(stderr, "Invalid command: '%s %s'\n\n", argv[0], argv[1]); + + return print_usage(ctx, argv[0], argc, argv); + + return 0; +} diff --git a/tools/automsg b/tools/automsg deleted file mode 100644 index a54d3d01..00000000 --- a/tools/automsg +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import yaml - -ocre_msg_file_template = """\ - -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - * - * @file messages.h - * - * @details This file contains all message types that components may send to one another. - * DO NOT EDIT THIS FILE. The file is auto-generated at build-time. - * - * How to add messages: - * 1. Define message types in the component, for example, components/your-component/message_types.h - * 2. Create a .yaml definition that maps your message type to a message name - * 3. Build! You can now use the message types in the component implementation - */ - -#ifndef OCRE_MESSAGES_H_G -#define OCRE_MESSAGES_H_G - -#include - -#include -{includes} - -struct base_msg {{ - int msg_id; - int *from; - struct base msg; -}}; - -{message_wrappers} - -{ocre_message} - -#endif""" - -component_message_type_includes_template = """\ -#include -""" - -msg_wrapper_template = """ -struct {message_name} {{ - int msg_id; - int *from; - struct {message_type} msg; -}}; -""" - -ocre_message = """\ -struct ocre_message {{ - uint32_t event; - uint32_t containerId; - union {{ -{message_unions} - }} components; -}};""" - -msg_union_template = """\ - union {{ -{messages} - struct base_msg base_msg; - }} {component}; -""" - -msg_union_member_template = """\ - struct {message_name} {message_name}; -""" - -def automsg(infiles, outfile): - wrapped_messages = set() - unioned_component = set() - component_message_type_includes = set() - - for filepath in infiles: - with open(filepath, 'r') as f: - messages = yaml.safe_load(f) - - component = messages['component'] - unioned_messages = set() - - component_message_type_includes.add(component_message_type_includes_template.format(component=component)) - - for event in messages['events']: - name = "{}_msg".format(event['type']) - type = event['type'] - - wrapped_messages.add(msg_wrapper_template.format(message_name=name, message_type=type)) - unioned_messages.add(msg_union_member_template.format(message_name=name)) - unioned_component.add(msg_union_template.format(component=component, messages=''.join(unioned_messages).strip('\n'))) - - ocre_msg = ocre_message.format(message_unions=''.join(unioned_component).strip('\n')) - - ocre_msg_file = ocre_msg_file_template.format( - includes=''.join(component_message_type_includes).strip('\n'), - message_wrappers=''.join(wrapped_messages).strip('\n'), - ocre_message=ocre_msg) - - with open(outfile, 'w') as f: - f.write(ocre_msg_file) - -if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument("infiles", nargs='+') - parser.add_argument("outfile", type=str) - args = parser.parse_args() - - automsg(args.infiles, args.outfile) - \ No newline at end of file diff --git a/wasm-micro-runtime b/wasm-micro-runtime index c9cf93fb..c065004e 160000 --- a/wasm-micro-runtime +++ b/wasm-micro-runtime @@ -1 +1 @@ -Subproject commit c9cf93fb10fe31e229658937a9afa2fbb41fb009 +Subproject commit c065004e8ca5228c3143c1fc93b78ea25135d6eb diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt new file mode 100644 index 00000000..2aa33b25 --- /dev/null +++ b/zephyr/CMakeLists.txt @@ -0,0 +1,27 @@ +# This file allows OCRE to be included as a Zephyr module. + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +set (WAMR_BUILD_PLATFORM "zephyr") + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set(CMAKE_C_STANDARD 99) +set(CMAKE_CXX_STANDARD 17) + +# include (../cmake/build_information.cmake) +include (wamr.cmake) + +add_subdirectory(../src/ocre "ocre-core") +add_subdirectory(../src/runtime "ocre-runtime") +add_subdirectory(../src/runtime/wamr "ocre-runtime-wamr") +add_subdirectory(../src/platform/zephyr "ocre-zephyr") +if(CONFIG_OCRE_SHELL) + message(STATUS "Shell is enabled") + add_subdirectory(../src/shell "ocre-shell") +endif() + +if(CONFIG_OCRE_STORAGE_PARTITION) + include(user_data.cmake) +endif() diff --git a/Kconfig b/zephyr/Kconfig similarity index 52% rename from Kconfig rename to zephyr/Kconfig index 701b0169..1b538c56 100644 --- a/Kconfig +++ b/zephyr/Kconfig @@ -1,101 +1,79 @@ -menu "Project Ocre options" - -source "Kconfig.zephyr" - config OCRE - bool "Project Ocre" - default y + bool "Ocre Runtime" + default n + select THREAD_STACK_INFO + select DYNAMIC_THREAD + select DYNAMIC_THREAD_ALLOC + select POSIX_API + select FLASH + select FLASH_MAP + select FILE_SYSTEM + select FILE_SYSTEM_LITTLEFS + select NETWORKING help Enable the Project Ocre runtime. - select PRINTK - select EVENTS - select EVENTFD - select FLASH - select FLASH_MAP - select FLASH_PAGE_LAYOUT - select FILE_SYSTEM - select FILE_SYSTEM_LITTLEFS - select REBOOT +if OCRE - select SETTINGS - select SETTINGS_RUNTIME +config OCRE_DEFAULT_WORKING_DIRECTORY + string "Default OCRE working directory" + default "/lfs/ocre" + help + Default working directory for OCRE. - select NETWORKING - select NET_SOCKETS - select NET_CONNECTION_MANAGER - select NET_UDP +# Default minimum system heap required by OCRE +config HEAP_MEM_POOL_ADD_SIZE_OCRE + def_int 16384 # 16KB - select SMF - select SMF_ANCESTOR_SUPPORT - select SMF_INITIAL_TRANSITION +comment "Storage partition" - # Enable the WASM Micro Runtime - select WAMR +config OCRE_STORAGE_PARTITION + bool "Enable building of storage partition binary" + default $(dt_nodelabel_exists,storage_partition) -config OCRE_CONTAINER_DEFAULT_HEAP_SIZE - int "Default value for the container heap size" - default 4096 - help - The default value used for a container's heap size. +if OCRE_STORAGE_PARTITION -config OCRE_CONTAINER_DEFAULT_STACK_SIZE - int "Default value for the container stack size" - default 2048 - help - The default value used for a container's stack size. - -config OCRE_LOG_DEBUG - bool "Debug logging" - default n - help - Enable Ocre debug logging - -config OCRE_LOG_ERR - bool "Error logging" - default n - help - Enable Ocre debug logging + config OCRE_STORAGE_PARTITION_ADDR + hex "User data partition address" + default "$(add_hex,$(dt_node_reg_addr_hex,$(dt_node_parent,$(dt_node_parent,$(dt_nodelabel_path,storage_partition)))),$(dt_nodelabel_reg_addr_hex,storage_partition))" + help + littlefs user data partition address. -config OCRE_LOG_WARN - bool "Warn logging" - default n +config OCRE_STORAGE_PARTITION_SIZE + int "User data partition size" + default $(dt_nodelabel_reg_size_int,storage_partition) help - Enable Ocre debug logging + littlefs user data partition size in bytes. -config OCRE_LOG_INF - bool "Info logging" - default n +config OCRE_STORAGE_PARTITION_BLOCK_SIZE + hex "User data partition block size" + default "0x1000" if !$(dt_node_has_prop,$(dt_node_parent,$(dt_node_parent,$(dt_nodelabel_path,storage_partition))),erase-block-size) + default "$(dt_node_int_prop_hex,$(dt_node_parent,$(dt_node_parent,$(dt_nodelabel_path,storage_partition))),erase-block-size)" help - Enable Ocre debug logging + littlefs user data partition size in bytes. -if OCRE - -module = OCRE -module-str = OCRE -source "subsys/logging/Kconfig.template.log_config" +config OCRE_MERGE_HEX + bool "Merge user_data partition in merged.hex" + default n + help + Enable to include littlefs formatted user_data partition + to be merged into merged.hex. endif -config OCRE_SENSORS - bool "Enable OCRE Sensors support" - default n - depends on SENSOR +comment "WAMR options" + +config OCRE_WAMR_INTERPRETER + bool "Enable WASM interpreter" + default y help - Enable support for OCRE sensors + Enable interpreting WASM code. -config RNG_SENSOR - bool "RNG Sensor" +config OCRE_WAMR_AOT + bool "Enable AOT execution" default n - depends on OCRE_SENSORS help - Enable support for the custom RNG sensor. - -config OCRE_WAMR_HEAP_BUFFER_SIZE - int "WAMR heap buffer size in bytes" - default 32768 - help - A static memory allocation for WAMR to use as a heap. + Enable execution of ahead of time compiled code. config OCRE_CONTAINER_DEFAULT_HEAP_SIZE int "Default value for the container heap size" @@ -108,109 +86,52 @@ config OCRE_CONTAINER_DEFAULT_STACK_SIZE default 2048 help The default value used for a container's stack size. - -config MAX_CONTAINERS - int "Maximum concurrent containers" - default 10 - help - The default value for maximum number of container's. - -config MAX_TIMERS - int "Maximum number of timers" - default 5 - help - Defines the maximum number of timers available in the system. -config MAX_SENSORS - int "Maximum number of sensors" - default 10 - help - Defines the maximum number of sensors that can be handled. +comment "Container features" -config MAX_CHANNELS_PER_SENSOR - int "Maximum number of channels per sensor" - default 5 +config OCRE_NETWORKING + bool "Enable container networking support" + default n help - Defines the maximum number of channels that each sensor can have. + Enable networking support for containers. -config OCRE_MEMORY_CHECK_ENABLED - bool "Enable memory availability checking for containers" - default y +config OCRE_CONTAINER_FILESYSTEM + bool "Enable Container file system support" + default n help - Enable runtime memory checks before creating containers - + Enable support for containers to access the filesystem -config OCRE_GPIO - bool "OCRE GPIO Driver" - default y - help - Enable the OCRE GPIO driver that provides a portable API layer - for GPIO operations across different hardware platforms. - - config OCRE_TIMER - bool "OCRE Timer Driver" - default y + bool "Enable OCRE Timer Driver" + select OCRE_CONTAINER_MESSAGING + default n help - Enable the OCRE Timer driver that provides a portable API layer - for Timer operations across different hardware platforms. + Enable the OCRE Timer driver that provides a portable API layer + for Timer operations across different hardware platforms. -config OCRE_GPIO_MAX_PINS - int "Maximum number of GPIO pins" - default 32 - help - Maximum number of GPIO pins that can be managed by the OCRE GPIO driver. - -config OCRE_GPIO_MAX_PORTS - int "Maximum number of GPIO ports" - default 4 - help - Maximum number of GPIO port devices that can be used by the OCRE GPIO driver. - -config OCRE_GPIO_PINS_PER_PORT - int "Number of pins per GPIO port" - default 32 +if OCRE_TIMER +config OCRE_MAX_TIMERS + int "Maximum number of timers" + default 8 help - Number of pins available on each GPIO port. This is used to map the - logical pin numbers to physical port and pin numbers. + Defines the maximum number of timers available in the system. +endif # OCRE_TIMER config OCRE_CONTAINER_MESSAGING bool "Enable OCRE Container Messaging support" default n help Enable support for OCRE Container Messaging - -config MESSAGING_MAX_SUBSCRIPTIONS - int "Number of maximum subscriptions for Container Messaging" - default 10 - depends on OCRE_CONTAINER_MESSAGING - help - Number of maximum subscriptions for Container Messaging - -config OCRE_CONTAINER_FILESYSTEM - bool "Enable OCRE Container File System support" - default n - help - Enable support for containers to access the flash filesystem -config OCRE_SHELL - bool "Enable OCRE Shell" - default y - help - Enable the OCRE Shell for dynamic configuration management. +if OCRE_CONTAINER_MESSAGING -config IMU_SENSOR - bool "IMU Sensor" - default n - depends on OCRE_SENSORS +config OCRE_MESSAGING_MAX_SUBSCRIPTIONS + int "Number of maximum subscriptions for Container Messaging" + default 16 help - Enable support for the custom IMU sensor. + Number of maximum subscriptions for Container Messaging -config OCRE_NETWORKING - bool "Enable container networking support" - default n - help - Enable networking support for containers. +endif # OCRE_CONTAINER_MESSAGING config OCRE_SHARED_HEAP bool "Enable container shared heap support" @@ -218,17 +139,10 @@ config OCRE_SHARED_HEAP help Enable shared heap support for containers. -config OCRE_SHARED_HEAP_BUF_SIZE - int "Shared heap buffer size in bytes" - default 65536 - depends on OCRE_SHARED_HEAP - help - Size of the pre-allocated buffer for the shared heap. - This memory is shared between WebAssembly modules. +if OCRE_SHARED_HEAP choice OCRE_SHARED_HEAP_MODE prompt "Shared heap mode" - depends on OCRE_SHARED_HEAP default OCRE_SHARED_HEAP_BUF_VIRTUAL help Select the shared heap memory mode: @@ -251,13 +165,139 @@ config OCRE_SHARED_HEAP_BUF_VIRTUAL endchoice +if OCRE_SHARED_HEAP_BUF_PHYSICAL + config OCRE_SHARED_HEAP_BUF_ADDRESS hex "Shared heap buffer address" default 0x00 - depends on OCRE_SHARED_HEAP help - Shared heap buffer address. - - For physical mode: Physical address of hardware registers - - For virtual mode: Leave as 0x00 to auto-allocate from RAM + Shared heap buffer address. Memory address of hardware registers. + +endif # OCRE_SHARED_HEAP_BUF_PHYSICAL + +config OCRE_SHARED_HEAP_BUF_SIZE + int "Shared heap buffer size in bytes" + default 65536 + help + Size of the pre-allocated buffer for the shared heap. + This memory is shared between WebAssembly modules. + +endif # OCRE_SHARED_HEAP + +comment "Control Interface" + +config OCRE_SHELL + bool "Enable OCRE Shell" + # depends on SHELL + default n + help + Enable the OCRE Shell for dynamic configuration management. + +comment "Logging" + +config OCRE_LOG_DEBUG + bool "Debug logging" + default n + help + Enable Ocre debug logging + +config OCRE_LOG_ERR + bool "Error logging" + default y + help + Enable Ocre debug logging + +config OCRE_LOG_WARN + bool "Warn logging" + default y + help + Enable Ocre debug logging + +config OCRE_LOG_INF + bool "Info logging" + default y + help + Enable Ocre debug logging + +module = OCRE +module-str = OCRE +source "subsys/logging/Kconfig.template.log_config" + +config OCRE_WAMR_LOG_LEVEL + int "Log level for WAMR" + default 0 + range 0 4 + help + Set the log level for the WAMR runtime: + 0: Fatal + 1: Error + 2: Warning + 3: Debug + 4: Verbose + +comment "Container hardware drivers" + +config OCRE_GPIO + bool "Enable OCRE GPIO Driver" + default n + help + Enable the OCRE GPIO driver that provides a portable API layer + for GPIO operations across different hardware platforms. + +if OCRE_GPIO +config OCRE_GPIO_MAX_PINS + int "Maximum number of GPIO pins" + default 32 + help + Maximum number of GPIO pins that can be managed by the OCRE GPIO driver. + +config OCRE_GPIO_MAX_PORTS + int "Maximum number of GPIO ports" + default 4 + help + Maximum number of GPIO port devices that can be used by the OCRE GPIO driver. + +config OCRE_GPIO_PINS_PER_PORT + int "Number of pins per GPIO port" + default 32 + help + Number of pins available on each GPIO port. This is used to map the + logical pin numbers to physical port and pin numbers. + +endif # OCRE_GPIO + +config OCRE_SENSORS + bool "Enable OCRE Sensors support" + default n + depends on SENSOR + help + Enable support for OCRE sensors + +if OCRE_SENSORS +config OCRE_MAX_SENSORS + int "Maximum number of sensors" + default 10 + help + Defines the maximum number of sensors that can be handled. + +config OCRE_MAX_CHANNELS_PER_SENSOR + int "Maximum number of channels per sensor" + default 5 + help + Defines the maximum number of channels that each sensor can have. + +config OCRE_RNG_SENSOR + bool "RNG Sensor" + default n + help + Enable support for the custom RNG sensor. + +config OCRE_IMU_SENSOR + bool "IMU Sensor" + default n + help + Enable support for the custom IMU sensor. + +endif # OCRE_SENSORS -endmenu +endif # OCRE diff --git a/zephyr/module.yml b/zephyr/module.yml index fabaab48..31c4472b 100644 --- a/zephyr/module.yml +++ b/zephyr/module.yml @@ -1,5 +1 @@ -name: project-ocre - -build: - cmake-ext: True - +name: ocre diff --git a/zephyr/user_data.cmake b/zephyr/user_data.cmake new file mode 100644 index 00000000..794c7d78 --- /dev/null +++ b/zephyr/user_data.cmake @@ -0,0 +1,28 @@ +cmake_minimum_required(VERSION 3.20.0) + +include(../cmake/state_information.cmake) + +add_custom_command(OUTPUT user_data.littlefs + COMMAND littlefs-python create --block-size ${CONFIG_OCRE_STORAGE_PARTITION_BLOCK_SIZE} --fs-size ${CONFIG_OCRE_STORAGE_PARTITION_SIZE} var/lib user_data.littlefs + DEPENDS ${OCRE_IMAGES} + COMMENT "Generating user_data.littlefs" + VERBATIM +) + +add_custom_command(OUTPUT user_data.littlefs.hex + COMMAND bin2hex.py --offset ${CONFIG_OCRE_STORAGE_PARTITION_ADDR} user_data.littlefs user_data.littlefs.hex + DEPENDS user_data.littlefs + COMMENT "Generating user_data.littlefs.hex" + VERBATIM +) + +add_custom_target(user_data_partition ALL + DEPENDS user_data.littlefs.hex + COMMENT "Generating user data partition" + VERBATIM +) + +if (CONFIG_OCRE_MERGE_HEX) + set_property(GLOBAL APPEND PROPERTY HEX_FILES_TO_MERGE "${CMAKE_CURRENT_BINARY_DIR}/user_data.littlefs.hex") + set_property(GLOBAL APPEND PROPERTY HEX_FILES_TO_MERGE "zephyr.hex") +endif() diff --git a/zephyr/wamr copy.cmake b/zephyr/wamr copy.cmake new file mode 100644 index 00000000..0055656c --- /dev/null +++ b/zephyr/wamr copy.cmake @@ -0,0 +1,63 @@ +# Determine the ISA of the target and set appropriately +if (DEFINED CONFIG_ISA_THUMB2) + set(TARGET_ISA THUMB) +elseif (DEFINED CONFIG_ISA_ARM) + set(TARGET_ISA ARM) +elseif (DEFINED CONFIG_X86) + set(TARGET_ISA X86_32) +elseif (DEFINED CONFIG_XTENSA) + set(TARGET_ISA XTENSA) +elseif (DEFINED CONFIG_RISCV) + set(TARGET_ISA RISCV32) +elseif (DEFINED CONFIG_ARCH_POSIX) + set(TARGET_ISA X86_32) +else () + message(FATAL_ERROR "Unsupported ISA: ${CONFIG_ARCH}") +endif () +message("TARGET ISA: ${TARGET_ISA}") + +add_compile_options(-O0 -Wno-unknown-attributes) + +# WAMR Options +set(WAMR_BUILD_PLATFORM "zephyr") +set(WAMR_BUILD_TARGET ${TARGET_ISA}) +set(WAMR_BUILD_INTERP 1) +set(WAMR_BUILD_FAST_INTERP 0) +set(WAMR_BUILD_AOT 0) +set(WAMR_BUILD_JIT 0) +set(WAMR_BUILD_LIBC_BUILTIN 1) +set(WAMR_BUILD_LIBC_WASI 1) +set(WAMR_BUILD_LIB_PTHREAD 1) +set(WAMR_BUILD_REF_TYPES 1) +set(WASM_ENABLE_LOG 1) + +# DEBUG +set(WAMR_BUILD_DEBUG_INTERP 1) + +if(NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_POOL) + set(WAMR_BUILD_GLOBAL_HEAP_POOL 1) +endif() +if(NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_SIZE) + set(WAMR_BUILD_GLOBAL_HEAP_SIZE 32767) +endif() + +enable_language (ASM) + +set (WAMR_BUILD_PLATFORM "zephyr") + +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../wasm-micro-runtime) + +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) + +# include(${WAMR_ROOT_DIR}/core/iwasm/libraries/lib-socket/lib_socket_wasi.cmake) + +add_library(vmlib) +target_sources(vmlib PRIVATE + ${WAMR_RUNTIME_LIB_SOURCE}) +target_link_libraries(vmlib zephyr_interface LITTLEFS) + +get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES) +target_include_directories(vmlib PUBLIC ${dirs}) + +get_property(defs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY COMPILE_DEFINITIONS) +target_compile_definitions(vmlib PRIVATE ${defs}) diff --git a/zephyr/wamr.cmake b/zephyr/wamr.cmake new file mode 100644 index 00000000..f2c7791a --- /dev/null +++ b/zephyr/wamr.cmake @@ -0,0 +1,62 @@ +# Determine the ISA of the target and set appropriately +if (DEFINED CONFIG_ISA_THUMB2) + set(TARGET_ISA THUMB) +elseif (DEFINED CONFIG_ISA_ARM) + set(TARGET_ISA ARM) +elseif (DEFINED CONFIG_X86) + set(TARGET_ISA X86_32) +elseif (DEFINED CONFIG_XTENSA) + set(TARGET_ISA XTENSA) +elseif (DEFINED CONFIG_RISCV) + set(TARGET_ISA RISCV32) +elseif (DEFINED CONFIG_ARCH_POSIX) + set(TARGET_ISA X86_32) +else () + message(FATAL_ERROR "Unsupported ISA: ${CONFIG_ARCH}") +endif () +message("Selected target ISA: ${TARGET_ISA}") + +# WAMR Options +set(WAMR_BUILD_PLATFORM "zephyr") +set(WAMR_BUILD_TARGET ${TARGET_ISA}) +set(WAMR_BUILD_INTERP 1) +set(WAMR_BUILD_FAST_INTERP 0) +set(WAMR_BUILD_AOT 0) +set(WAMR_BUILD_JIT 0) +set(WAMR_BUILD_LIBC_BUILTIN 1) +set(WAMR_BUILD_LIBC_WASI 1) +set(WAMR_BUILD_LIB_PTHREAD 1) +set(WAMR_BUILD_REF_TYPES 1) +set(WAMR_BUILD_SHARED_HEAP 1) +set(WASM_ENABLE_LOG 1) + +# DEBUG +#set(WAMR_BUILD_DEBUG_INTERP 1) + +if(NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_POOL) + set(WAMR_BUILD_GLOBAL_HEAP_POOL 1) +endif() +if(NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_SIZE) + set(WAMR_BUILD_GLOBAL_HEAP_SIZE 32767) +endif() + +enable_language (ASM) + +set (WAMR_BUILD_PLATFORM "zephyr") + +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../wasm-micro-runtime) + +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) + +# include(${WAMR_ROOT_DIR}/core/iwasm/libraries/lib-socket/lib_socket_wasi.cmake) + +add_library(vmlib) +target_sources(vmlib PRIVATE + ${WAMR_RUNTIME_LIB_SOURCE}) +target_link_libraries(vmlib zephyr_interface LITTLEFS) + +get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES) +target_include_directories(vmlib PUBLIC ${dirs}) + +get_property(defs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY COMPILE_DEFINITIONS) +target_compile_definitions(vmlib PRIVATE ${defs}) From 879775b60e8a87f24d5059b12564dfbd33698535 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 8 Dec 2025 16:43:39 +0100 Subject: [PATCH 036/234] zephyr: rename user_data to storage_partition user_data is not used anywhere, and storage_partition is the standard name used for this partition in most zephyr boards which support it. Signed-off-by: Marco Casaroli --- .../boards/pico_plus2_rp2350b_m33_w.overlay | 4 ++-- .../boards/pico_plus2_rp2350b_m33_w.overlay | 4 ++-- .../zephyr/boards/b_u585i_iot02a.overlay | 18 +++++++++--------- .../boards/pico_plus2_rp2350b_m33_w.overlay | 4 ++-- zephyr/CMakeLists.txt | 2 +- ...user_data.cmake => storage_partition.cmake} | 0 6 files changed, 16 insertions(+), 16 deletions(-) rename zephyr/{user_data.cmake => storage_partition.cmake} (100%) diff --git a/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay b/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay index 58910875..383637bc 100644 --- a/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay +++ b/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay @@ -4,7 +4,7 @@ #address-cells = <1>; #size-cells = <1>; - user_data_partition: storage_partition: partition@600000 { + storage_partition: partition@600000 { label = "storage"; reg = <0x410000 0x800000>; }; @@ -21,7 +21,7 @@ cache-size = <256>; lookahead-size = <256>; block-cycles = <512>; - partition = <&user_data_partition>; + partition = <&storage_partition>; mount-point = "/lfs"; automount; }; diff --git a/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay b/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay index 58910875..383637bc 100644 --- a/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay +++ b/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay @@ -4,7 +4,7 @@ #address-cells = <1>; #size-cells = <1>; - user_data_partition: storage_partition: partition@600000 { + storage_partition: partition@600000 { label = "storage"; reg = <0x410000 0x800000>; }; @@ -21,7 +21,7 @@ cache-size = <256>; lookahead-size = <256>; block-cycles = <512>; - partition = <&user_data_partition>; + partition = <&storage_partition>; mount-point = "/lfs"; automount; }; diff --git a/src/samples/supervisor/zephyr/boards/b_u585i_iot02a.overlay b/src/samples/supervisor/zephyr/boards/b_u585i_iot02a.overlay index 7f2a0d0c..a27fe2e9 100644 --- a/src/samples/supervisor/zephyr/boards/b_u585i_iot02a.overlay +++ b/src/samples/supervisor/zephyr/boards/b_u585i_iot02a.overlay @@ -48,7 +48,7 @@ // Add labels for sensors defined in the board .dtsi file, and any other user configuration // This is required so we can reference them in the devices block above, which is used by ocre_sensors &i2c2 { - ism330dhcx: ism330dhcx@6b { + ism330dhcx: ism330dhcx@6b { label = "imu"; status = "okay"; accel-odr = <4>; // 104 Hz @@ -56,19 +56,19 @@ gyro-odr = <4>; // 104 Hz gyro-range = <250>; // ±250 dps }; - lps22hh: lps22hh@5d { + lps22hh: lps22hh@5d { label = "pressure"; status = "okay"; }; - hts221: hts221@5f { + hts221: hts221@5f { label = "humidity"; status = "okay"; }; - iis2mdc: iis2mdc@1e { + iis2mdc: iis2mdc@1e { label = "magnetometer"; status = "okay"; }; - veml6030: veml6030@10 { + veml6030: veml6030@10 { label = "light"; status = "okay"; }; @@ -89,7 +89,7 @@ /* Flash partitions - 2MB total, no MCUboot */ &flash0 { /delete-node/ partitions; - + partitions { compatible = "fixed-partitions"; #address-cells = <1>; @@ -102,7 +102,7 @@ }; /* Dummy slot1 partition for MCUboot compatibility (unused) */ slot1_partition: partition@1F5000 { - label = "image-1"; + label = "image-1"; reg = <0x001F5000 DT_SIZE_K(44)>; }; }; @@ -115,7 +115,7 @@ /delete-node/ partition; /* Use the whole flash for the filesystem. */ - user_data_partition: storage_partition: partition@0 { + storage_partition: partition@0 { label = "user_data"; reg = <0x00000000 DT_SIZE_M(64)>; }; @@ -132,7 +132,7 @@ cache-size = <256>; lookahead-size = <256>; block-cycles = <512>; - partition = <&user_data_partition>; + partition = <&storage_partition>; mount-point = "/lfs"; automount; }; diff --git a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay index 58910875..383637bc 100644 --- a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay +++ b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay @@ -4,7 +4,7 @@ #address-cells = <1>; #size-cells = <1>; - user_data_partition: storage_partition: partition@600000 { + storage_partition: partition@600000 { label = "storage"; reg = <0x410000 0x800000>; }; @@ -21,7 +21,7 @@ cache-size = <256>; lookahead-size = <256>; block-cycles = <512>; - partition = <&user_data_partition>; + partition = <&storage_partition>; mount-point = "/lfs"; automount; }; diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 2aa33b25..dc626e13 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -23,5 +23,5 @@ if(CONFIG_OCRE_SHELL) endif() if(CONFIG_OCRE_STORAGE_PARTITION) - include(user_data.cmake) + include(storage_partition.cmake) endif() diff --git a/zephyr/user_data.cmake b/zephyr/storage_partition.cmake similarity index 100% rename from zephyr/user_data.cmake rename to zephyr/storage_partition.cmake From 904d83f23c38053c2c234c51f262e45bfe6c17ea Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 8 Dec 2025 21:30:09 +0100 Subject: [PATCH 037/234] fix(ocre_timer): memory leak We need to delete the timer when we are done, otherwise, there is a memory leak. Signed-off-by: Marco Casaroli --- src/runtime/wamr/ocre_api/core/core_external.h | 8 ++++++++ src/runtime/wamr/ocre_api/core/core_timer.c | 9 +++++++++ src/runtime/wamr/ocre_api/ocre_timers/ocre_timer.c | 7 +++++++ 3 files changed, 24 insertions(+) diff --git a/src/runtime/wamr/ocre_api/core/core_external.h b/src/runtime/wamr/ocre_api/core/core_external.h index c99876f3..afdd4b7a 100644 --- a/src/runtime/wamr/ocre_api/core/core_external.h +++ b/src/runtime/wamr/ocre_api/core/core_external.h @@ -174,6 +174,14 @@ int core_timer_start(core_timer_t *timer, int timeout_ms, int period_ms); */ int core_timer_stop(core_timer_t *timer); +/** + * @brief Deletes a timer. + * + * @param timer Pointer to the timer structure. + * @return 0 on success, negative value on error. + */ +int core_timer_delete(core_timer_t *timer); + /** * @brief Get file status (size). * diff --git a/src/runtime/wamr/ocre_api/core/core_timer.c b/src/runtime/wamr/ocre_api/core/core_timer.c index a758e70a..be2f1461 100644 --- a/src/runtime/wamr/ocre_api/core/core_timer.c +++ b/src/runtime/wamr/ocre_api/core/core_timer.c @@ -57,3 +57,12 @@ int core_timer_stop(core_timer_t *timer) struct itimerspec its = {0}; return timer_settime(timer->timerid, 0, &its, NULL); } + +int core_timer_delete(core_timer_t *timer) +{ + if (!timer) + return -1; + + fprintf(stderr, "FINAL TIMER DELETEEEE!!!!!!!!\n"); + return timer_delete(timer->timerid); +} diff --git a/src/runtime/wamr/ocre_api/ocre_timers/ocre_timer.c b/src/runtime/wamr/ocre_api/ocre_timers/ocre_timer.c index 5c14a279..414f8079 100644 --- a/src/runtime/wamr/ocre_api/ocre_timers/ocre_timer.c +++ b/src/runtime/wamr/ocre_api/ocre_timers/ocre_timer.c @@ -103,6 +103,9 @@ int ocre_timer_delete(wasm_exec_env_t exec_env, ocre_timer_t id) // Stop unified core timer core_timer_stop(&timer->timer); + // Delete unified core timer + core_timer_delete(&timer->timer); + timer->in_use = 0; timer->running = 0; timer->owner = NULL; @@ -211,6 +214,10 @@ void ocre_timer_cleanup_container(wasm_module_inst_t module_inst) if (timers[i].in_use && timers[i].owner == module_inst) { // Stop unified core timer core_timer_stop(&timers[i].timer); + + // Delete unified core timer + core_timer_delete(&timers[i].timer); + timers[i].in_use = 0; timers[i].running = 0; timers[i].owner = NULL; From 462cf240872d86ab64b73de12228250c43dccf19 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 8 Dec 2025 21:31:16 +0100 Subject: [PATCH 038/234] fix(container): remove We should ibe able to remove containers that are in ERROR state. Signed-off-by: Marco Casaroli --- src/ocre/container.c | 3 ++- src/shell/container/rm.c | 23 ++++++++++++----------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/ocre/container.c b/src/ocre/container.c index a58d7b72..34db9cf9 100644 --- a/src/ocre/container.c +++ b/src/ocre/container.c @@ -240,7 +240,8 @@ int ocre_container_destroy(struct ocre_container *container) } ocre_container_status_t status = ocre_container_status_locked(container); - if (status != OCRE_CONTAINER_STATUS_STOPPED && status != OCRE_CONTAINER_STATUS_CREATED) { + if (status != OCRE_CONTAINER_STATUS_STOPPED && status != OCRE_CONTAINER_STATUS_CREATED && + status != OCRE_CONTAINER_STATUS_ERROR) { LOG_ERR("Cannot remove container '%s' because it is in use", container->id); return -1; } diff --git a/src/shell/container/rm.c b/src/shell/container/rm.c index 7005783a..8d939c93 100644 --- a/src/shell/container/rm.c +++ b/src/shell/container/rm.c @@ -14,19 +14,20 @@ static int usage(const char *argv0) int cmd_container_rm(struct ocre_context *ctx, char *argv0, int argc, char **argv) { if (argc == 2) { - struct ocre_container *container = ocre_context_get_container_by_id(ctx, argv[1]); - if (!container) { - fprintf(stderr, "Failed to get container '%s'\n", argv[1]); - return -1; - } + struct ocre_container *container = ocre_context_get_container_by_id(ctx, argv[1]); + if (!container) { + fprintf(stderr, "Failed to get container '%s'\n", argv[1]); + return -1; + } - ocre_container_status_t status = ocre_container_get_status(container); - if (status != OCRE_CONTAINER_STATUS_STOPPED && status != OCRE_CONTAINER_STATUS_CREATED) { - fprintf(stderr, "Container '%s' is in use\n", argv[1]); - return -1; - } + ocre_container_status_t status = ocre_container_get_status(container); + if (status != OCRE_CONTAINER_STATUS_STOPPED && status != OCRE_CONTAINER_STATUS_CREATED && + status != OCRE_CONTAINER_STATUS_ERROR) { + fprintf(stderr, "Container '%s' is in use\n", argv[1]); + return -1; + } - return ocre_context_remove_container(ctx, container); + return ocre_context_remove_container(ctx, container); } else { fprintf(stderr, "'%s container rm' requires exactly one argument\n\n", argv0); return usage(argv0); From 4a0c89d63750731937d394e76861005195460f5b Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 8 Dec 2025 21:32:12 +0100 Subject: [PATCH 039/234] fix(wamr): improve handling of ocre_api We only register and unregister if the capability is enabled. Signed-off-by: Marco Casaroli --- src/runtime/wamr/wamr.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/runtime/wamr/wamr.c b/src/runtime/wamr/wamr.c index 60bc327c..2bb2c6fd 100644 --- a/src/runtime/wamr/wamr.c +++ b/src/runtime/wamr/wamr.c @@ -57,6 +57,12 @@ static int instance_execute(void *runtime_context) } } + if (context->uses_ocre_api) { + // Cleanup module resources if using OCRE API + LOG_INF("Cleaning up module resources"); + ocre_cleanup_module_resources(module_inst); + } + LOG_INF("Context %p completed successfully", context); return wasm_runtime_get_wasi_exit_code(context->module_inst); @@ -344,7 +350,9 @@ static int instance_destroy(void *runtime_context) return -1; } - ocre_unregister_module(context->module_inst); + if (context->uses_ocre_api) { + ocre_unregister_module(context->module_inst); + } wasm_runtime_deinstantiate(context->module_inst); context->module_inst = NULL; From 11fe56b403d67be30f2479850c43c51ba2139649 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 8 Dec 2025 21:32:53 +0100 Subject: [PATCH 040/234] fix(wamr): improve handling of main exit When main exits with error, it might not be an error. The function could have been stopped by the user. Continue, cleanup and return the status code. Signed-off-by: Marco Casaroli --- src/runtime/wamr/wamr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/runtime/wamr/wamr.c b/src/runtime/wamr/wamr.c index 2bb2c6fd..d2f401ea 100644 --- a/src/runtime/wamr/wamr.c +++ b/src/runtime/wamr/wamr.c @@ -48,12 +48,11 @@ static int instance_execute(void *runtime_context) // Execute main function const char *exception = NULL; if (!wasm_application_execute_main(module_inst, 1, context->argv)) { - LOG_ERR("Failed to execute main function in context %p exception: %s", context, + LOG_WRN("Main function returned error in context %p exception: %s", context, exception ? exception : "None"); exception = wasm_runtime_get_exception(module_inst); if (exception) { LOG_ERR("Container %p exception: %s", context, exception); - return -1; } } From c682845c27302443e1673bdc9f384e98e20a5d46 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 8 Dec 2025 21:35:48 +0100 Subject: [PATCH 041/234] fix(zephyr): bump number of threads and reserved heap To be able to support many containers and threads. Signed-off-by: Marco Casaroli --- src/samples/supervisor/zephyr/prj.conf | 2 +- zephyr/Kconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/samples/supervisor/zephyr/prj.conf b/src/samples/supervisor/zephyr/prj.conf index 3ef6c14b..18b243f8 100644 --- a/src/samples/supervisor/zephyr/prj.conf +++ b/src/samples/supervisor/zephyr/prj.conf @@ -32,7 +32,7 @@ CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=-1 CONFIG_SHELL_STACK_SIZE=8192 CONFIG_MAX_PTHREAD_MUTEX_COUNT=32 -CONFIG_POSIX_THREAD_THREADS_MAX=10 +CONFIG_POSIX_THREAD_THREADS_MAX=32 # Ocre configuration CONFIG_OCRE=y diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 1b538c56..c8beb5ec 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -23,7 +23,7 @@ config OCRE_DEFAULT_WORKING_DIRECTORY # Default minimum system heap required by OCRE config HEAP_MEM_POOL_ADD_SIZE_OCRE - def_int 16384 # 16KB + def_int 32768 # 32KB comment "Storage partition" From 8cc33ab4194637bc4071e05c53da323ebed190ce Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 8 Dec 2025 21:36:32 +0100 Subject: [PATCH 042/234] build: do not build supervisor posix This will be enabled in the future. Signed-off-by: Marco Casaroli --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fa3ac6aa..359eb87f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,5 +34,4 @@ add_subdirectory(src/shell) # samples add_subdirectory(src/samples/mini/posix) add_subdirectory(src/samples/demo/posix) -add_subdirectory(src/samples/supervisor/posix) add_subdirectory(src/samples/bash_runtime/posix) From 6f47454e98dc84b2d7e61774461f57bba3d12435 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 8 Dec 2025 21:39:33 +0100 Subject: [PATCH 043/234] fix(shared_heap): use correct symbol Use correct symbol defined in Kconfig or config.h Signed-off-by: Marco Casaroli --- src/platform/posix/include/ocre/platform/config.h | 2 +- src/runtime/wamr/wamr.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/platform/posix/include/ocre/platform/config.h b/src/platform/posix/include/ocre/platform/config.h index b00b72b6..f59b2a60 100644 --- a/src/platform/posix/include/ocre/platform/config.h +++ b/src/platform/posix/include/ocre/platform/config.h @@ -18,6 +18,6 @@ #define CONFIG_OCRE_MESSAGING_MAX_SUBSCRIPTIONS 32 #define CONFIG_OCRE_SHARED_HEAP 1 #define CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL 1 -#define OCRE_SHARED_HEAP_BUF_SIZE 131072 +#define CONFIG_OCRE_SHARED_HEAP_BUF_SIZE 131072 #endif /* OCRE_PLATFORM_POSIX_H */ diff --git a/src/runtime/wamr/wamr.c b/src/runtime/wamr/wamr.c index d2f401ea..68bbe2e7 100644 --- a/src/runtime/wamr/wamr.c +++ b/src/runtime/wamr/wamr.c @@ -82,13 +82,13 @@ static int runtime_init(void) { #if defined(CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL) /* Allocate memory for the shared heap */ - shared_heap_buf = user_malloc(OCRE_SHARED_HEAP_BUF_SIZE); + shared_heap_buf = user_malloc(CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL); if (!shared_heap_buf) { - LOG_ERR("Failed to allocate memory for the shared heap of size %zu", (size_t)OCRE_SHARED_HEAP_BUF_SIZE); + LOG_ERR("Failed to allocate memory for the shared heap of size %zu", (size_t)CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL); return -1; } #elif defined(CONFIG_OCRE_SHARED_HEAP_BUF_PHYSICAL) - shared_heap_buf = OCRE_SHARED_HEAP_BUF_ADDRESS; + shared_heap_buf = CONFIG_OCRE_SHARED_HEAP_BUF_ADDRESS; #endif RuntimeInitArgs init_args; memset(&init_args, 0, sizeof(RuntimeInitArgs)); @@ -111,7 +111,7 @@ static int runtime_init(void) SharedHeapInitArgs heap_init_args; memset(&heap_init_args, 0, sizeof(heap_init_args)); heap_init_args.pre_allocated_addr = shared_heap_buf; - heap_init_args.size = OCRE_SHARED_HEAP_BUF_SIZE; + heap_init_args.size = CONFIG_OCRE_SHARED_HEAP_BUF_SIZE; _shared_heap = wasm_runtime_create_shared_heap(&heap_init_args); From fae7c1db6f5a5bee3f8de08774cd21a3ad00eb58 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 8 Dec 2025 22:02:54 +0100 Subject: [PATCH 044/234] fix(container): stack use after scope random_id should be available when we call ocre_container_create Signed-off-by: Marco Casaroli --- src/ocre/context.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ocre/context.c b/src/ocre/context.c index c6ca26b8..52413072 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -146,8 +146,9 @@ struct ocre_container *ocre_context_create_container(struct ocre_context *contex /* If no container ID is provided, generate a random one */ + char random_id[RANDOM_ID_LEN]; + if (!container_id) { - char random_id[RANDOM_ID_LEN]; if (make_unique_random_container_id(context, random_id, RANDOM_ID_LEN)) { LOG_ERR("Failed to generate random container ID"); goto unlock_mutex; From cb3fb61173c4be527562667f9bd6eb05e78ad997 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 8 Dec 2025 22:06:27 +0100 Subject: [PATCH 045/234] Remove spurious log message Does not belong here. Signed-off-by: Marco Casaroli --- src/runtime/wamr/ocre_api/core/core_timer.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/runtime/wamr/ocre_api/core/core_timer.c b/src/runtime/wamr/ocre_api/core/core_timer.c index be2f1461..33332e45 100644 --- a/src/runtime/wamr/ocre_api/core/core_timer.c +++ b/src/runtime/wamr/ocre_api/core/core_timer.c @@ -63,6 +63,5 @@ int core_timer_delete(core_timer_t *timer) if (!timer) return -1; - fprintf(stderr, "FINAL TIMER DELETEEEE!!!!!!!!\n"); return timer_delete(timer->timerid); } From 30754c5e286741d98949737a31f0623fdb4aea40 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 8 Dec 2025 22:08:23 +0100 Subject: [PATCH 046/234] fix(posix): remove shell We will enable this later. For now, just remove so it builds. Signed-off-by: Marco Casaroli --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 359eb87f..d5574913 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,7 @@ add_subdirectory(src/runtime/wamr) add_subdirectory(src/platform/posix) # shell -add_subdirectory(src/shell) +#add_subdirectory(src/shell) # samples add_subdirectory(src/samples/mini/posix) From 8c8267efb18aba02b8a4236e223a52ec0a6549fc Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 8 Dec 2025 22:08:52 +0100 Subject: [PATCH 047/234] feat(samples): demo Some random container management. Signed-off-by: Marco Casaroli --- src/samples/demo/main.c | 120 ++++++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 54 deletions(-) diff --git a/src/samples/demo/main.c b/src/samples/demo/main.c index d6296ff0..66fc5308 100644 --- a/src/samples/demo/main.c +++ b/src/samples/demo/main.c @@ -10,6 +10,7 @@ const struct ocre_container_args args = { int main(int argc, char *argv[]) { int rc; + int status; rc = ocre_initialize(); if (rc) { @@ -64,7 +65,6 @@ int main(int argc, char *argv[]) return 1; } - int status; rc = ocre_container_wait(blinky, &status); if (rc) { fprintf(stderr, "Failed to wait for container\n"); @@ -73,75 +73,87 @@ int main(int argc, char *argv[]) fprintf(stderr, "Container exited with status %d\n", status); - // rc = ocre_context_remove_container(ocre, blinky); - // if (rc) { - // fprintf(stderr, "Failed to remove container\n"); - // return 1; - // } + rc = ocre_context_remove_container(ocre, blinky); + if (rc) { + fprintf(stderr, "Failed to remove container\n"); + return 1; + } + + struct ocre_container *subscriber = + ocre_context_create_container(ocre, "subscriber.wasm", "wamr", NULL, true, &args); + + if (!subscriber) { + fprintf(stderr, "Failed to create container\n"); + return 1; + } - // struct ocre_container *subscriber = - // ocre_context_create_container(ocre, "subscriber.wasm", "wamr", NULL, true, &args); + struct ocre_container *publisher = + ocre_context_create_container(ocre, "publisher.wasm", "wamr", NULL, true, &args); - // if (!subscriber) { - // fprintf(stderr, "Failed to create container\n"); - // return 1; - // } + if (!publisher) { + fprintf(stderr, "Failed to create container\n"); + return 1; + } - // struct ocre_container *publisher = - // ocre_context_create_container(ocre, "publisher.wasm", "wamr", NULL, true, &args); + rc = ocre_container_start(subscriber); + if (rc) { + fprintf(stderr, "Failed to start container\n"); + return 1; + } - // if (!publisher) { - // fprintf(stderr, "Failed to create container\n"); - // return 1; - // } + sleep(1); - // rc = ocre_container_start(subscriber); - // if (rc) { - // fprintf(stderr, "Failed to start container\n"); - // return 1; - // } + rc = ocre_container_start(publisher); + if (rc) { + fprintf(stderr, "Failed to start container\n"); + return 1; + } - // sleep(5); + sleep(5); - // rc = ocre_container_start(publisher); - // if (rc) { - // fprintf(stderr, "Failed to start container\n"); - // return 1; - // } + rc = ocre_container_kill(subscriber); + if (rc) { + fprintf(stderr, "Failed to kill container\n"); + return 1; + } - // sleep(10); + rc = ocre_container_kill(publisher); + if (rc) { + fprintf(stderr, "Failed to kill container\n"); + return 1; + } - // rc = ocre_container_kill(subscriber); - // if (rc) { - // fprintf(stderr, "Failed to kill container\n"); - // return 1; - // } + rc = ocre_container_wait(subscriber, &status); + if (rc) { + fprintf(stderr, "Failed to wait for container\n"); + return 1; + } - // rc = ocre_container_kill(publisher); - // if (rc) { - // fprintf(stderr, "Failed to kill container\n"); - // return 1; - // } + fprintf(stderr, "Subscriber exited with status %d\n", status); - // rc = ocre_container_wait(subscriber, &status); - // if (rc) { - // fprintf(stderr, "Failed to wait for container\n"); - // return 1; - // } + rc = ocre_container_wait(publisher, &status); + if (rc) { + fprintf(stderr, "Failed to wait for container\n"); + return 1; + } - // fprintf(stderr, "Container exited with status %d\n", status); + fprintf(stderr, "Publisher exited with status %d\n", status); - // rc = ocre_container_wait(publisher, &status); - // if (rc) { - // fprintf(stderr, "Failed to wait for container\n"); - // return 1; - // } + rc = ocre_context_remove_container(ocre, subscriber); + if (rc) { + fprintf(stderr, "Failed to remove subscriber\n"); + return 1; + } - // fprintf(stderr, "Container exited with status %d\n", status); + rc = ocre_context_remove_container(ocre, publisher); + if (rc) { + fprintf(stderr, "Failed to remove publisher\n"); + return 1; + } - // ocre_destroy_context(ocre); + ocre_destroy_context(ocre); - // ocre_deinitialize(); + ocre_deinitialize(); return 0; } From 86041ed161bde4e126c7c4f42d746fd3551e4282 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 9 Dec 2025 09:40:48 +0100 Subject: [PATCH 048/234] add uthash LICENSE Adds the license file. Signed-off-by: Marco Casaroli --- src/ocre/include/uthash/LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/ocre/include/uthash/LICENSE diff --git a/src/ocre/include/uthash/LICENSE b/src/ocre/include/uthash/LICENSE new file mode 100644 index 00000000..ce887671 --- /dev/null +++ b/src/ocre/include/uthash/LICENSE @@ -0,0 +1,21 @@ +Copyright (c) 2005-2025, Troy D. Hanson https://troydhanson.github.io/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + From d6b9f267eae729dde7d0e19c60108b25f8c7ec0c Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 9 Dec 2025 16:51:36 +0100 Subject: [PATCH 049/234] feat(context): add rm_rf function Which removes a directory recusively only by using basic functions and not making recursive calls. Signed-off-by: Marco Casaroli --- src/ocre/CMakeLists.txt | 1 + src/ocre/util/rm_rf.c | 324 ++++++++++++++++++++++++++++++++++++++++ src/ocre/util/rm_rf.h | 44 ++++++ 3 files changed, 369 insertions(+) create mode 100644 src/ocre/util/rm_rf.c create mode 100644 src/ocre/util/rm_rf.h diff --git a/src/ocre/CMakeLists.txt b/src/ocre/CMakeLists.txt index 455ff2b6..23933496 100644 --- a/src/ocre/CMakeLists.txt +++ b/src/ocre/CMakeLists.txt @@ -47,6 +47,7 @@ target_sources(OcreCore unique_random_id.c ocre.c util/string_array.c + util/rm_rf.c commit_id.h include/ocre/build_info.h ) diff --git a/src/ocre/util/rm_rf.c b/src/ocre/util/rm_rf.c new file mode 100644 index 00000000..0d73e579 --- /dev/null +++ b/src/ocre/util/rm_rf.c @@ -0,0 +1,324 @@ +#include +#include +#include +#include +#include +#include +#include + +/* AI generated code: please don't joke */ + +/* Stack node for directory traversal */ +struct dir_stack_node { + char *path; + DIR *dir; + int is_removal_phase; + struct dir_stack_node *next; +}; + +/* Stack operations */ +static struct dir_stack_node* push_dir(struct dir_stack_node *stack, const char *path, int is_removal_phase) { + struct dir_stack_node *node = malloc(sizeof(struct dir_stack_node)); + if (!node) { + return NULL; + } + + node->path = strdup(path); + if (!node->path) { + free(node); + return NULL; + } + + node->dir = NULL; + node->is_removal_phase = is_removal_phase; + node->next = stack; + + return node; +} + +static struct dir_stack_node* pop_dir(struct dir_stack_node *stack) { + if (!stack) { + return NULL; + } + + struct dir_stack_node *next = stack->next; + + if (stack->dir) { + closedir(stack->dir); + } + free(stack->path); + free(stack); + + return next; +} + +/* Build full path by concatenating directory and filename */ +static char* build_path(const char *dir, const char *name) { + size_t dir_len = strlen(dir); + size_t name_len = strlen(name); + size_t total_len = dir_len + name_len + 2; /* +1 for '/', +1 for '\0' */ + + char *path = malloc(total_len); + if (!path) { + return NULL; + } + + snprintf(path, total_len, "%s/%s", dir, name); + return path; +} + +/* Remove directory recursively using stack-based traversal (no function recursion) */ +int rm_rf(const char *path) { + if (!path) { + errno = EINVAL; + return -1; + } + + struct stat st; + if (stat(path, &st) == -1) { + return -1; /* errno already set by stat */ + } + + /* If it's a regular file, just remove it */ + if (!S_ISDIR(st.st_mode)) { + return unlink(path); + } + + /* Stack for directory traversal */ + struct dir_stack_node *stack = NULL; + int result = 0; + + /* Push initial directory onto stack */ + stack = push_dir(stack, path, 0); + if (!stack) { + errno = ENOMEM; + return -1; + } + + /* Process stack until empty */ + while (stack) { + struct dir_stack_node *current = stack; + + if (current->is_removal_phase) { + /* This directory has been processed, now remove it */ + if (rmdir(current->path) == -1) { + result = -1; + /* Continue processing to clean up stack */ + } + stack = pop_dir(stack); + continue; + } + + /* First time processing this directory */ + if (!current->dir) { + current->dir = opendir(current->path); + if (!current->dir) { + result = -1; + stack = pop_dir(stack); + continue; + } + } + + /* Read next directory entry */ + struct dirent *entry = readdir(current->dir); + if (!entry) { + /* No more entries, mark for removal and continue */ + current->is_removal_phase = 1; + continue; + } + + /* Skip . and .. entries */ + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { + continue; + } + + /* Build full path for this entry */ + char *entry_path = build_path(current->path, entry->d_name); + if (!entry_path) { + result = -1; + errno = ENOMEM; + break; + } + + /* Get entry information */ + if (stat(entry_path, &st) == -1) { + result = -1; + free(entry_path); + continue; + } + + if (S_ISDIR(st.st_mode)) { + /* It's a directory - push it onto stack for processing */ + struct dir_stack_node *new_node = push_dir(stack, entry_path, 0); + if (!new_node) { + result = -1; + errno = ENOMEM; + free(entry_path); + break; + } + stack = new_node; + } else { + /* It's a file - remove it directly */ + if (unlink(entry_path) == -1) { + result = -1; + /* Continue processing other entries */ + } + } + + free(entry_path); + } + + /* Clean up remaining stack in case of error */ + while (stack) { + stack = pop_dir(stack); + } + + return result; +} + +/* Alternative version with more detailed error reporting */ +int rm_rf_verbose(const char *path, int (*error_callback)(const char *path, int error_code)) { + if (!path) { + if (error_callback) { + error_callback(path, EINVAL); + } + errno = EINVAL; + return -1; + } + + struct stat st; + if (stat(path, &st) == -1) { + if (error_callback) { + error_callback(path, errno); + } + return -1; + } + + /* If it's a regular file, just remove it */ + if (!S_ISDIR(st.st_mode)) { + if (unlink(path) == -1) { + if (error_callback) { + error_callback(path, errno); + } + return -1; + } + return 0; + } + + /* Stack for directory traversal */ + struct dir_stack_node *stack = NULL; + int result = 0; + + /* Push initial directory onto stack */ + stack = push_dir(stack, path, 0); + if (!stack) { + if (error_callback) { + error_callback(path, ENOMEM); + } + errno = ENOMEM; + return -1; + } + + /* Process stack until empty */ + while (stack) { + struct dir_stack_node *current = stack; + + if (current->is_removal_phase) { + /* This directory has been processed, now remove it */ + if (rmdir(current->path) == -1) { + if (error_callback) { + error_callback(current->path, errno); + } + result = -1; + } + stack = pop_dir(stack); + continue; + } + + /* First time processing this directory */ + if (!current->dir) { + current->dir = opendir(current->path); + if (!current->dir) { + if (error_callback) { + error_callback(current->path, errno); + } + result = -1; + stack = pop_dir(stack); + continue; + } + } + + /* Read next directory entry */ + errno = 0; /* Clear errno before readdir */ + struct dirent *entry = readdir(current->dir); + if (!entry) { + if (errno != 0) { + if (error_callback) { + error_callback(current->path, errno); + } + result = -1; + } + /* No more entries, mark for removal and continue */ + current->is_removal_phase = 1; + continue; + } + + /* Skip . and .. entries */ + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { + continue; + } + + /* Build full path for this entry */ + char *entry_path = build_path(current->path, entry->d_name); + if (!entry_path) { + if (error_callback) { + error_callback("memory allocation", ENOMEM); + } + result = -1; + errno = ENOMEM; + break; + } + + /* Get entry information */ + if (stat(entry_path, &st) == -1) { + if (error_callback) { + error_callback(entry_path, errno); + } + result = -1; + free(entry_path); + continue; + } + + if (S_ISDIR(st.st_mode)) { + /* It's a directory - push it onto stack for processing */ + struct dir_stack_node *new_node = push_dir(stack, entry_path, 0); + if (!new_node) { + if (error_callback) { + error_callback(entry_path, ENOMEM); + } + result = -1; + errno = ENOMEM; + free(entry_path); + break; + } + stack = new_node; + } else { + /* It's a file - remove it directly */ + if (unlink(entry_path) == -1) { + if (error_callback) { + error_callback(entry_path, errno); + } + result = -1; + } + } + + free(entry_path); + } + + /* Clean up remaining stack in case of error */ + while (stack) { + stack = pop_dir(stack); + } + + return result; +} diff --git a/src/ocre/util/rm_rf.h b/src/ocre/util/rm_rf.h new file mode 100644 index 00000000..6cfe36b0 --- /dev/null +++ b/src/ocre/util/rm_rf.h @@ -0,0 +1,44 @@ +#ifndef RM_RF_H +#define RM_RF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Remove a file or directory recursively. + * + * This function removes the specified path and all its contents recursively. + * It uses a stack-based approach to traverse directories without function recursion. + * + * @param path The path to the file or directory to remove + * @return 0 on success, -1 on error (errno is set appropriately) + * + * Note: This function will attempt to remove as many files/directories as possible + * even if some operations fail. The return value indicates if any errors occurred. + */ +int rm_rf(const char *path); + +/** + * Remove a file or directory recursively with error callback. + * + * This function is similar to rm_rf() but provides detailed error reporting + * through a callback function that is called for each error encountered. + * + * @param path The path to the file or directory to remove + * @param error_callback Callback function called for each error. Should return 0 + * to continue processing, non-zero to abort. Can be NULL. + * Parameters: (const char *failed_path, int error_code) + * @return 0 on success, -1 on error (errno is set appropriately) + * + * The error_callback receives: + * - failed_path: The path that caused the error (or descriptive string for memory errors) + * - error_code: The errno value associated with the error + */ +int rm_rf_verbose(const char *path, int (*error_callback)(const char *path, int error_code)); + +#ifdef __cplusplus +} +#endif + +#endif /* RM_RF_H */ \ No newline at end of file From a628320208b0658f8a8c72f11202079a37bb9543 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 9 Dec 2025 16:54:16 +0100 Subject: [PATCH 050/234] feat(string_array): add function to search for an item A shortcut to lookup something on the list. Signed-off-by: Marco Casaroli --- src/ocre/util/string_array.c | 15 +++++++++++++++ src/ocre/util/string_array.h | 1 + 2 files changed, 16 insertions(+) diff --git a/src/ocre/util/string_array.c b/src/ocre/util/string_array.c index af6e0d46..4d11446f 100644 --- a/src/ocre/util/string_array.c +++ b/src/ocre/util/string_array.c @@ -107,3 +107,18 @@ size_t string_array_copy(char **dest, char **src) return count; } + +const char *string_array_lookup(const char **array, const char *key) +{ + if (!array || !key) { + return NULL; + } + + for (size_t i = 0; array[i]; i++) { + if (!strcmp(array[i], key)) { + return array[i]; + } + } + + return NULL; +} diff --git a/src/ocre/util/string_array.h b/src/ocre/util/string_array.h index d4ca2182..2fabaf65 100644 --- a/src/ocre/util/string_array.h +++ b/src/ocre/util/string_array.h @@ -4,3 +4,4 @@ char **string_array_dup(char **src); char **string_array_deep_dup(const char **const src); void string_array_free(char **array); size_t string_array_copy(char **dest, char **src); +const char *string_array_lookup(const char **array, const char *key); From 292cb7f295a829a7c628186d0abfbb5a7a6c8456 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 9 Dec 2025 16:49:55 +0100 Subject: [PATCH 051/234] feat(context): manage working directory The context needs to manage the working directory of containers. Signed-off-by: Marco Casaroli --- src/ocre/context.c | 107 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 82 insertions(+), 25 deletions(-) diff --git a/src/ocre/context.c b/src/ocre/context.c index 52413072..ce4d9fe2 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -3,6 +3,7 @@ #include #include #include +#include #include @@ -12,6 +13,8 @@ #include "container.h" #include "unique_random_id.h" +#include "util/rm_rf.h" +#include "util/string_array.h" #define RANDOM_ID_LEN 8 @@ -25,6 +28,7 @@ struct ocre_context { struct container_node { struct ocre_container *container; + char *working_directory; struct container_node *next; /* needed for singly- or doubly-linked lists */ }; @@ -136,6 +140,10 @@ struct ocre_container *ocre_context_create_container(struct ocre_context *contex { const char *computed_container_id = NULL; struct ocre_container *container = NULL; + struct container_node *node = NULL; + char *container_workdir = NULL; + char *image_path = NULL; + char random_id[RANDOM_ID_LEN]; int rc; rc = pthread_mutex_lock(&context->mutex); @@ -144,65 +152,103 @@ struct ocre_container *ocre_context_create_container(struct ocre_context *contex return NULL; } - /* If no container ID is provided, generate a random one */ - - char random_id[RANDOM_ID_LEN]; + /* Container name checks */ if (!container_id) { + /* If no container ID is provided, generate a random one */ + if (make_unique_random_container_id(context, random_id, RANDOM_ID_LEN)) { LOG_ERR("Failed to generate random container ID"); - goto unlock_mutex; + goto error; } computed_container_id = random_id; } else if (ocre_context_get_container_by_id_locked(context, container_id)) { LOG_ERR("Container with ID '%s' already exists", container_id); - goto unlock_mutex; + goto error; } else { computed_container_id = container_id; } + /* Allocate the node */ + + node = malloc(sizeof(struct container_node)); + if (!node) { + LOG_ERR("Failed to allocate memory for container node"); + goto error; + } + + memset(node, 0, sizeof(struct container_node)); + /* Build the absolute path to the image */ - char *abs_path = malloc(strlen(context->working_directory) + strlen("/images/") + strlen(image) + 1); - if (!abs_path) { + image_path = malloc(strlen(context->working_directory) + strlen("/images/") + strlen(image) + 1); + if (!image_path) { LOG_ERR("Failed to allocate memory for absolute path"); - goto unlock_mutex; + goto error; } - strcpy(abs_path, context->working_directory); - strcat(abs_path, "/images/"); - strcat(abs_path, image); + strcpy(image_path, context->working_directory); + strcat(image_path, "/images/"); + strcat(image_path, image); + + // TODO: check if image exists + + /* Build the absolute path to the working dir and create it */ + + if (arguments && string_array_lookup(arguments->capabilities, "filesystem")) { + container_workdir = + malloc(strlen(context->working_directory) + strlen("/containers/") + strlen(container_id) + 1); + if (!container_workdir) { + LOG_ERR("Failed to allocate memory for working directory"); + goto error; + } + + snprintf(container_workdir, + strlen(context->working_directory) + strlen("/containers/") + strlen(container_id) + 1, + "%s/containers/%s", context->working_directory, container_id); + + rc = mkdir(container_workdir, 0755); + if (rc) { + LOG_ERR("Failed to create working directory '%s': rc=%d", container_workdir, rc); + goto error; + } + } /* Create the container */ - container = ocre_container_create(abs_path, runtime, computed_container_id, detached, arguments); + container = ocre_container_create(image_path, runtime, computed_container_id, detached, arguments); if (!container) { LOG_ERR("Failed to create container %s: errno=%d", computed_container_id, errno); - goto free_path; + goto error; } /* Add the container to the context */ - struct container_node *node = malloc(sizeof(struct container_node)); - if (!node) { - LOG_ERR("Failed to allocate memory for container node"); - goto error_container; - } - node->container = container; + node->working_directory = container_workdir; LL_APPEND(context->containers, node); - goto free_path; + goto success; + +error: + if (container_workdir) { + rc = rm_rf(container_workdir); + if (rc) { + LOG_ERR("Failed to remove container working directory '%s': rc=%d", container_workdir, rc); + } + } + + free(container_workdir); + + free(node); -error_container: - ocre_container_destroy(container); + /* Fall-through on error */ -free_path: - free(abs_path); +success: + free(image_path); -unlock_mutex: rc = pthread_mutex_unlock(&context->mutex); if (rc) { LOG_ERR("Failed to unlock context mutex: rc=%d", rc); @@ -230,7 +276,18 @@ int ocre_context_remove_container(struct ocre_context *context, struct ocre_cont return rc; } + if (node->working_directory) { + rc = rm_rf(node->working_directory); + if (rc) { + LOG_ERR("Failed to remove container working directory '%s': rc=%d", + node->working_directory, rc); + } + } + LL_DELETE(context->containers, node); + + free(node->working_directory); + free(node); return 0; From db84c07ebb21d07785158d2c1dbaa06c890b0958 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 9 Dec 2025 16:50:34 +0100 Subject: [PATCH 052/234] fix(context): improve cleanup of containers on termination We also take the chance to improve the error handling of the context creation, and some formatting fixes. Signed-off-by: Marco Casaroli --- src/ocre/context.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/ocre/context.c b/src/ocre/context.c index ce4d9fe2..f9d7991d 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -55,13 +55,13 @@ struct ocre_context *ocre_create_context(const char *workdir) if (!context->working_directory) { LOG_ERR("Failed to allocate memory for working directory: errno=%d", errno); free(context); - goto error_context; + goto error; } rc = pthread_mutex_init(&context->mutex, NULL); if (rc) { LOG_ERR("Failed to initialize context mutex: rc=%d", rc); - goto error_workdir; + goto error; } /* Initialize containers list */ @@ -70,10 +70,9 @@ struct ocre_context *ocre_create_context(const char *workdir) return context; -error_workdir: +error: free(context->working_directory); -error_context: free(context); return NULL; @@ -123,6 +122,13 @@ void ocre_context_destroy(struct ocre_context *context) ocre_container_wait(node->container, NULL); } + /* Remove all containers */ + + LL_FOREACH(context->containers, node) + { + ocre_context_remove_container(context, node->container); + } + int rc; rc = pthread_mutex_destroy(&context->mutex); if (rc) { @@ -325,10 +331,11 @@ int ocre_context_get_num_containers(struct ocre_context *context) return count; } -char *ocre_context_get_working_directory(struct ocre_context *context) { - /* We never change this, no need to lock */ +char *ocre_context_get_working_directory(struct ocre_context *context) +{ + /* We never change this, no need to lock */ - return context->working_directory; + return context->working_directory; } int ocre_context_list_containers(struct ocre_context *context, struct ocre_container **containers, int max_size) From 481a5d8825bd3646eea18e3b28c41e2ac21c6f3d Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 9 Dec 2025 18:53:46 +0100 Subject: [PATCH 053/234] feat(runner_vtable): use workdir Workdir will be used as the root filesystem of the container. Signed-off-by: Marco Casaroli --- src/ocre/container.c | 5 +++-- src/runtime/include/ocre/runtime/vtable.h | 4 ++-- src/runtime/wamr/wamr.c | 15 ++++++++------- src/samples/bash_runtime/posix/bash/bash.c | 6 +++--- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/ocre/container.c b/src/ocre/container.c index 34db9cf9..52271860 100644 --- a/src/ocre/container.c +++ b/src/ocre/container.c @@ -194,8 +194,9 @@ struct ocre_container *ocre_container_create(const char *path, const char *runti goto error_mutex; } - container->runtime_context = container->runtime->create( - path, 8192, 8192, capabilities, (const char **)container->argv, (const char **)container->envp, mounts); + container->runtime_context = + container->runtime->create(img_path, workdir, 8192, 8192, capabilities, (const char **)container->argv, + (const char **)container->envp, mounts); if (!container->runtime_context) { LOG_ERR("Failed to create container"); goto error_cond; diff --git a/src/runtime/include/ocre/runtime/vtable.h b/src/runtime/include/ocre/runtime/vtable.h index b7bffbf1..4f56f790 100644 --- a/src/runtime/include/ocre/runtime/vtable.h +++ b/src/runtime/include/ocre/runtime/vtable.h @@ -8,8 +8,8 @@ struct ocre_runtime_vtable { int (*init)(void); int (*deinit)(void); - void *(*create)(const char *path, size_t stack_size, size_t heap_size, const char **capabilities, - const char **argv, const char **envp, const char **mounts); + void *(*create)(const char *img_path, const char *workdir, size_t stack_size, size_t heap_size, + const char **capabilities, const char **argv, const char **envp, const char **mounts); int (*destroy)(void *runtime_context); int (*thread_execute)(void *arg); int (*kill)(void *runtime_context); diff --git a/src/runtime/wamr/wamr.c b/src/runtime/wamr/wamr.c index 68bbe2e7..212f1af2 100644 --- a/src/runtime/wamr/wamr.c +++ b/src/runtime/wamr/wamr.c @@ -84,7 +84,8 @@ static int runtime_init(void) /* Allocate memory for the shared heap */ shared_heap_buf = user_malloc(CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL); if (!shared_heap_buf) { - LOG_ERR("Failed to allocate memory for the shared heap of size %zu", (size_t)CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL); + LOG_ERR("Failed to allocate memory for the shared heap of size %zu", + (size_t)CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL); return -1; } #elif defined(CONFIG_OCRE_SHARED_HEAP_BUF_PHYSICAL) @@ -158,10 +159,10 @@ static int runtime_deinit(void) return 0; } -static void *instance_create(const char *path, size_t stack_size, size_t heap_size, const char **capabilities, - const char **argv, const char **envp, const char **mounts) +static void *instance_create(const char *img_path, const char *workdir, size_t stack_size, size_t heap_size, + const char **capabilities, const char **argv, const char **envp, const char **mounts) { - if (!path) { + if (!img_path) { LOG_ERR("Invalid arguments"); return NULL; } @@ -199,7 +200,7 @@ static void *instance_create(const char *path, size_t stack_size, size_t heap_si memset(context->argv, 0, sizeof(char *) * (argc + 2)); - context->argv[0] = strdup(path); + context->argv[0] = strdup(img_path); if (!context->argv[0]) { goto error_argv; } @@ -218,7 +219,7 @@ static void *instance_create(const char *path, size_t stack_size, size_t heap_si LOG_WRN("Buffer already allocated. Possible memory leak!"); } - context->buffer = ocre_load_file(path, &context->size); + context->buffer = ocre_load_file(img_path, &context->size); if (!context->buffer) { LOG_ERR("Failed to load wasm program into buffer errno=%d", errno); goto error_argv; @@ -350,7 +351,7 @@ static int instance_destroy(void *runtime_context) } if (context->uses_ocre_api) { - ocre_unregister_module(context->module_inst); + ocre_unregister_module(context->module_inst); } wasm_runtime_deinstantiate(context->module_inst); diff --git a/src/samples/bash_runtime/posix/bash/bash.c b/src/samples/bash_runtime/posix/bash/bash.c index 2c49908f..77ce7965 100644 --- a/src/samples/bash_runtime/posix/bash/bash.c +++ b/src/samples/bash_runtime/posix/bash/bash.c @@ -62,10 +62,10 @@ static int instance_thread_execute(void *arg) return ret; } -static void *instance_create(const char *path, size_t stack_size, size_t heap_size, const char **capabilities, +static void *instance_create(const char *img_path, const char *workdir, size_t stack_size, size_t heap_size, const char **capabilities, const char **argv, const char **envp, const char **mounts) { - if (!path) { + if (!img_path) { LOG_ERR("Invalid arguments"); return NULL; } @@ -108,7 +108,7 @@ static void *instance_create(const char *path, size_t stack_size, size_t heap_si goto error_argv; } - context->argv[1] = strdup(path); + context->argv[1] = strdup(img_path); if (!context->argv[1]) { goto error_argv; } From 41dca3c112400ee452d52dcffb6832ce8a2fa29e Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 9 Dec 2025 19:25:21 +0100 Subject: [PATCH 054/234] feat(context): pass workdir to container The container needs its working directory that is created by the context. Signed-off-by: Marco Casaroli --- src/ocre/container.c | 6 +++--- src/ocre/container.h | 5 +++-- src/ocre/context.c | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/ocre/container.c b/src/ocre/container.c index 52271860..4e4f589e 100644 --- a/src/ocre/container.c +++ b/src/ocre/container.c @@ -10,7 +10,6 @@ #include #include "ocre.h" -#include "context.h" #include "container.h" #include "util/string_array.h" @@ -120,8 +119,9 @@ static ocre_container_status_t ocre_container_status_locked(struct ocre_containe return container->status; } -struct ocre_container *ocre_container_create(const char *path, const char *runtime, const char *container_id, - bool detached, const struct ocre_container_args *arguments) +struct ocre_container *ocre_container_create(const char *img_path, const char *workdir, const char *runtime, + const char *container_id, bool detached, + const struct ocre_container_args *arguments) { int rc; const char **capabilities = NULL; diff --git a/src/ocre/container.h b/src/ocre/container.h index 7c16fd57..79c10437 100644 --- a/src/ocre/container.h +++ b/src/ocre/container.h @@ -2,7 +2,8 @@ struct ocre_container; -struct ocre_container *ocre_container_create(const char *path, const char *runtime, const char *container_id, - bool detached, const struct ocre_container_args *arguments); +struct ocre_container *ocre_container_create(const char *img_path, const char *workdir, const char *runtime, + const char *container_id, bool detached, + const struct ocre_container_args *arguments); int ocre_container_destroy(struct ocre_container *container); int ocre_container_id_compare(const struct ocre_container *container, const char *id); diff --git a/src/ocre/context.c b/src/ocre/context.c index f9d7991d..441e905d 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -223,7 +223,7 @@ struct ocre_container *ocre_context_create_container(struct ocre_context *contex /* Create the container */ - container = ocre_container_create(image_path, runtime, computed_container_id, detached, arguments); + container = ocre_container_create(image_path, container_workdir, runtime, computed_container_id, detached, arguments); if (!container) { LOG_ERR("Failed to create container %s: errno=%d", computed_container_id, errno); goto error; From 9ad2de1a0c1cffb5b23dfea9f32e89f7c7c63722 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 9 Dec 2025 19:28:46 +0100 Subject: [PATCH 055/234] fix(wamr): pause, unpause stubs and formatting fixes Signed-off-by: Marco Casaroli --- src/runtime/include/ocre/runtime/vtable.h | 1 + src/runtime/wamr/wamr.c | 72 +++++++++++++++++++---- 2 files changed, 60 insertions(+), 13 deletions(-) diff --git a/src/runtime/include/ocre/runtime/vtable.h b/src/runtime/include/ocre/runtime/vtable.h index 4f56f790..cb155b84 100644 --- a/src/runtime/include/ocre/runtime/vtable.h +++ b/src/runtime/include/ocre/runtime/vtable.h @@ -12,6 +12,7 @@ struct ocre_runtime_vtable { const char **capabilities, const char **argv, const char **envp, const char **mounts); int (*destroy)(void *runtime_context); int (*thread_execute)(void *arg); + int (*stop)(void *runtime_context); int (*kill)(void *runtime_context); int (*pause)(void *runtime_context); int (*unpause)(void *runtime_context); diff --git a/src/runtime/wamr/wamr.c b/src/runtime/wamr/wamr.c index 212f1af2..67213b55 100644 --- a/src/runtime/wamr/wamr.c +++ b/src/runtime/wamr/wamr.c @@ -42,14 +42,17 @@ static int instance_execute(void *runtime_context) struct wamr_context *context = runtime_context; wasm_module_inst_t module_inst = context->module_inst; - // Clear any previous exceptions + /* Clear any previous exceptions */ + wasm_runtime_clear_exception(module_inst); - // Execute main function + /* Execute main function */ + const char *exception = NULL; if (!wasm_application_execute_main(module_inst, 1, context->argv)) { LOG_WRN("Main function returned error in context %p exception: %s", context, exception ? exception : "None"); + exception = wasm_runtime_get_exception(module_inst); if (exception) { LOG_ERR("Container %p exception: %s", context, exception); @@ -57,8 +60,10 @@ static int instance_execute(void *runtime_context) } if (context->uses_ocre_api) { - // Cleanup module resources if using OCRE API + /* Cleanup module resources if using OCRE API */ + LOG_INF("Cleaning up module resources"); + ocre_cleanup_module_resources(module_inst); } @@ -72,7 +77,9 @@ static int instance_thread_execute(void *arg) struct wamr_context *context = arg; wasm_runtime_init_thread_env(); + int ret = instance_execute(context); + wasm_runtime_destroy_thread_env(); return ret; @@ -81,7 +88,9 @@ static int instance_thread_execute(void *arg) static int runtime_init(void) { #if defined(CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL) + /* Allocate memory for the shared heap */ + shared_heap_buf = user_malloc(CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL); if (!shared_heap_buf) { LOG_ERR("Failed to allocate memory for the shared heap of size %zu", @@ -129,11 +138,11 @@ static int runtime_init(void) ocre_common_init(); ocre_timer_init(); + // TODO handle error return 0; -// error_shared_heap: error_runtime: wasm_runtime_destroy(); @@ -175,8 +184,10 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s memset(context, 0, sizeof(struct wamr_context)); - // For envp we can just keep a reference - // as the container is guaranteed to only free it after our destruction + /* For envp we can just keep a reference + * as the container is guaranteed to only free it after our destruction + */ + context->envp = (char **)envp; int envn = 0; @@ -184,14 +195,17 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s envn++; } - // We need to insert argv[0]. We can keep a shallow copy, because - // the container is guaranteed to only free it after us + /* We need to insert argv[0]. We can keep a shallow copy, because + * the container is guaranteed to only free it after us + */ + int argc = 0; while (argv && argv[argc]) { argc++; } - // 2 more: app name and NULL + /* 2 more: app name and NULL */ + context->argv = malloc(sizeof(char *) * (argc + 2)); if (!context->argv) { LOG_ERR("Failed to allocate memory for argv"); @@ -219,6 +233,8 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s LOG_WRN("Buffer already allocated. Possible memory leak!"); } + /* Memory-map file */ + context->buffer = ocre_load_file(img_path, &context->size); if (!context->buffer) { LOG_ERR("Failed to load wasm program into buffer errno=%d", errno); @@ -237,6 +253,8 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s const char **dir_map_list = NULL; size_t dir_map_list_len = 0; + /* Process capabilities */ + for (const char **cap = capabilities; cap && *cap; cap++) { if (!strcmp(*cap, "networking")) { const char *addr_pool[] = { @@ -305,7 +323,8 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s context->buffer = NULL; error_argv: - // only free what we allocated + /* Only free what we allocated */ + free(context->argv[0]); free(context->argv); @@ -315,6 +334,19 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s return NULL; } +static int instance_stop(void *runtime_context) +{ + struct wamr_context *context = runtime_context; + + if (!context) { + return -1; + } + + // TODO + + return -1; +} + static int instance_kill(void *runtime_context) { struct wamr_context *context = runtime_context; @@ -336,10 +368,22 @@ static int instance_pause(void *runtime_context) return -1; } + // TODO + return -1; - // wasm_runtime_terminate(context->module_inst); +} - return 0; +static int instance_unpause(void *runtime_context) +{ + struct wamr_context *context = runtime_context; + + if (!context) { + return -1; + } + + // TODO + + return -1; } static int instance_destroy(void *runtime_context) @@ -355,6 +399,7 @@ static int instance_destroy(void *runtime_context) } wasm_runtime_deinstantiate(context->module_inst); + context->module_inst = NULL; wasm_runtime_unload(context->module); @@ -380,6 +425,7 @@ const struct ocre_runtime_vtable wamr_vtable = { .destroy = instance_destroy, .thread_execute = instance_thread_execute, .kill = instance_kill, + .stop = instance_stop, .pause = instance_pause, - // .unpause = instance_unpause, + .unpause = instance_unpause, }; From c170854651c960fd37454340ef19fe798ef8ae43 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 9 Dec 2025 19:30:15 +0100 Subject: [PATCH 056/234] fix(container): img path Signed-off-by: Marco Casaroli --- src/ocre/container.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ocre/container.c b/src/ocre/container.c index 4e4f589e..cfaf1074 100644 --- a/src/ocre/container.c +++ b/src/ocre/container.c @@ -143,11 +143,11 @@ struct ocre_container *ocre_container_create(const char *img_path, const char *w /* Strip the image name from the path, just to make it look nicer */ - const char *image = strrchr(path, '/'); + const char *image = strrchr(img_path, '/'); if (image) { image++; } else { - image = path; + image = img_path; } container->image = strdup(image); @@ -206,7 +206,7 @@ struct ocre_container *ocre_container_create(const char *img_path, const char *w container->detached = detached; - LOG_INF("Created container '%s' with runtime '%s' (path '%s')", container->id, runtime, path); + LOG_INF("Created container '%s' with runtime '%s' (path '%s')", container->id, runtime, img_path); return container; From 54c86fd788f30eaae10fecf623bc7b7edde6f7dc Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 9 Dec 2025 19:31:04 +0100 Subject: [PATCH 057/234] fix(ocre): remove unused functions Signed-off-by: Marco Casaroli --- src/ocre/include/ocre/ocre.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/ocre/include/ocre/ocre.h b/src/ocre/include/ocre/ocre.h index abd745ab..276f2f88 100644 --- a/src/ocre/include/ocre/ocre.h +++ b/src/ocre/include/ocre/ocre.h @@ -29,12 +29,6 @@ extern const struct ocre_config ocre_build_configuration; struct ocre_context; -// struct ocre_context_status { -// int num_containers; -// int num_running_containers; -// char *ocre_workdir; -// }; - struct ocre_container_args { const char **argv; const char **envp; @@ -57,7 +51,6 @@ struct ocre_context *ocre_create_context(const char *workdir); void ocre_destroy_context(struct ocre_context *context); void ocre_deinitialize(void); -// int ocre_context_get_status(const struct ocre_context_status *status); struct ocre_container *ocre_context_create_container(struct ocre_context *context, const char *image, const char *const runtime, const char *container_id, bool detached, const struct ocre_container_args *arguments); From 7ebed6e0209e581f40a9781c214f87a7a3c4de00 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 9 Dec 2025 19:31:29 +0100 Subject: [PATCH 058/234] fix(samples/demo): improve logging Signed-off-by: Marco Casaroli --- src/samples/demo/main.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/samples/demo/main.c b/src/samples/demo/main.c index 66fc5308..8d4d2a18 100644 --- a/src/samples/demo/main.c +++ b/src/samples/demo/main.c @@ -113,19 +113,19 @@ int main(int argc, char *argv[]) rc = ocre_container_kill(subscriber); if (rc) { - fprintf(stderr, "Failed to kill container\n"); + fprintf(stderr, "Failed to kill subscriber container\n"); return 1; } rc = ocre_container_kill(publisher); if (rc) { - fprintf(stderr, "Failed to kill container\n"); + fprintf(stderr, "Failed to kill publisher container\n"); return 1; } rc = ocre_container_wait(subscriber, &status); if (rc) { - fprintf(stderr, "Failed to wait for container\n"); + fprintf(stderr, "Failed to wait for subscriber container\n"); return 1; } @@ -133,7 +133,7 @@ int main(int argc, char *argv[]) rc = ocre_container_wait(publisher, &status); if (rc) { - fprintf(stderr, "Failed to wait for container\n"); + fprintf(stderr, "Failed to wait for publisher container\n"); return 1; } @@ -155,5 +155,7 @@ int main(int argc, char *argv[]) ocre_deinitialize(); + fprintf(stdout, "Demo completed successfully\n"); + return 0; } From 081b7e2852a808b95bd4135fee7f0f50c5ec6300 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 9 Dec 2025 19:32:54 +0100 Subject: [PATCH 059/234] chore: remove .zed dir Signed-off-by: Marco Casaroli --- .zed/debug.json | 22 ---------------------- .zed/tasks.json | 16 ---------------- 2 files changed, 38 deletions(-) delete mode 100644 .zed/debug.json delete mode 100644 .zed/tasks.json diff --git a/.zed/debug.json b/.zed/debug.json deleted file mode 100644 index f231e8f6..00000000 --- a/.zed/debug.json +++ /dev/null @@ -1,22 +0,0 @@ -// Project-local debug tasks -// -// For more documentation on how to configure debug tasks, -// see: https://zed.dev/docs/debugger - -[ - { - "adapter": "CodeLLDB", - "label": "Debug ", - "request": "launch", - // "program": "build/src/samples/bash_runtime/posix/ocre_bash", - // "program": "build/src/samples/mini/posix/ocre_mini", - "program": "build/src/samples/supervisor/posix/ocre", - "args": ["container", "ps"], - "cwd": "$ZED_WORKTREE_ROOT/build" - // "build": { - // "command": "make", - // // "args": ["build", "-j8"], - // "cwd": "$ZED_WORKTREE_ROOT/build" - // } - } -] diff --git a/.zed/tasks.json b/.zed/tasks.json deleted file mode 100644 index 99a563a0..00000000 --- a/.zed/tasks.json +++ /dev/null @@ -1,16 +0,0 @@ -[ - { - "label": "DevContainer: Up", - "command": "devcontainer up - workspace-folder ${ZED_WORKTREE_ROOT}", - "use_new_terminal": true, - "allow_concurrent_runs": false, - "reveal": "always" - }, - { - "label": "DevContainer: Build", - "command": "devcontainer build - workspace-folder ${ZED_WORKTREE_ROOT}", - "use_new_terminal": true, - "allow_concurrent_runs": false, - "reveal": "always" - } -] From 372f654e22ecb538e0ab6bdfca9d3f704b5e72ce Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 9 Dec 2025 19:46:21 +0100 Subject: [PATCH 060/234] feat(shell/create): process mount points We do the early error checking so we can notify the user of the error. We also, process the points and pass them correctly to ocre. Signed-off-by: Marco Casaroli --- src/shell/container/create.c | 41 +++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/shell/container/create.c b/src/shell/container/create.c index 91bf4aec..654a0a2a 100644 --- a/src/shell/container/create.c +++ b/src/shell/container/create.c @@ -43,9 +43,11 @@ int cmd_container_create_run(struct ocre_context *ctx, char *argv0, int argc, ch char *container_id = NULL; const char **capabilities = NULL; const char **environment = NULL; + const char **mounts = NULL; size_t capabilities_count = 0; size_t environment_count = 0; + size_t mounts_count = 0; opterr = 0; @@ -83,7 +85,39 @@ int cmd_container_create_run(struct ocre_context *ctx, char *argv0, int argc, ch continue; } case 'v': { - fprintf(stderr, "Volume '%s' will be mounted\n", optarg); + + /* Check mounts parameters of format : + * Destination should be absolute path + * We do not like anything to be mounted at '/' + * We handle '/' with the 'filesystem' capability. + */ + + if (optarg[0] != '/') { + fprintf(stderr, "Invalid mount format: '%s': source must be absolute path", optarg); + return NULL; + } + + char *dst = strchr(optarg, ':'); + if (!dst) { + fprintf(stderr, "Invalid mount format: '%s': must be :", optarg); + return NULL; + } + + dst++; + + if (dst[0] != '/') { + fprintf(stderr, "Invalid mount format: '%s': destination must be absolute path", + optarg); + return NULL; + } + + if (dst[1] == '\0') { + fprintf(stderr, "Invalid mount format: '%s': destination must not be '/'", optarg); + return NULL; + } + + mounts = realloc(mounts, sizeof(char *) * (mounts_count + 1)); + mounts[mounts_count++] = optarg; continue; } case 'k': { @@ -110,6 +144,9 @@ int cmd_container_create_run(struct ocre_context *ctx, char *argv0, int argc, ch capabilities = realloc(capabilities, sizeof(char *) * (capabilities_count + 1)); capabilities[capabilities_count++] = NULL; + mounts = realloc(mounts, sizeof(char *) * (mounts_count + 1)); + mounts[mounts_count++] = NULL; + if (optind >= argc) { fprintf(stderr, "'%s container %s' requires at least one non option argument\n\n", argv0, argv[0]); return usage(argv0, argv[0]); @@ -120,6 +157,7 @@ int cmd_container_create_run(struct ocre_context *ctx, char *argv0, int argc, ch .argv = (const char **)&argv[optind + 1], .capabilities = capabilities, .envp = environment, + .mounts = mounts, }; struct ocre_container *container = @@ -146,6 +184,7 @@ int cmd_container_create_run(struct ocre_context *ctx, char *argv0, int argc, ch ret = 0; cleanup: + free(mounts); free(capabilities); free(environment); From 7f2c093d6b3358e393f2efd4c678a6eadc96cb0a Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 9 Dec 2025 19:47:06 +0100 Subject: [PATCH 061/234] feat(container): process mount parameters Signed-off-by: Marco Casaroli --- src/ocre/container.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/ocre/container.c b/src/ocre/container.c index cfaf1074..22a101a3 100644 --- a/src/ocre/container.c +++ b/src/ocre/container.c @@ -132,6 +132,43 @@ struct ocre_container *ocre_container_create(const char *img_path, const char *w return NULL; } + /* Check mounts parameters of format : + * Destination should be absolute path + * We do not like anything to be mounted at '/' + * We handle '/' with the 'filesystem' capability. + */ + + if (arguments->mounts) { + const char **mount = arguments->mounts; + + while (*mount) { + if (*mount[0] != '/') { + LOG_ERR("Invalid mount format: '%s': source must be absolute path", *mount); + return NULL; + } + + char *dst = strchr(*mount, ':'); + if (!dst) { + LOG_ERR("Invalid mount format: '%s': must be :", *mount); + return NULL; + } + + dst++; + + if (dst[0] != '/') { + LOG_ERR("Invalid mount format: '%s': destination must be absolute path", *mount); + return NULL; + } + + if (dst[1] == '\0') { + LOG_ERR("Invalid mount format: '%s': destination must not be '/'", *mount); + return NULL; + } + + mount++; + } + } + struct ocre_container *container = malloc(sizeof(struct ocre_container)); if (!container) { From f1f99f40e67eca2d159cdd9e747d0deabce557e6 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 9 Dec 2025 20:52:49 +0100 Subject: [PATCH 062/234] feat(context): cleanup container workdirs Clean the spurious workdirs without containers. Signed-off-by: Marco Casaroli --- src/ocre/context.c | 73 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 65 insertions(+), 8 deletions(-) diff --git a/src/ocre/context.c b/src/ocre/context.c index 441e905d..514e1dae 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -32,6 +33,58 @@ struct container_node { struct container_node *next; /* needed for singly- or doubly-linked lists */ }; +static int delete_container_workdirs(const char *working_directory) +{ + int ret = -1; + DIR *d = NULL; + struct dirent *dir = NULL; + + char *containers_path = malloc(strlen(working_directory) + strlen("/containers") + 1); + if (!containers_path) { + LOG_ERR("Failed to allocate memory for container workdir path"); + return -1; + } + + sprintf(containers_path, "%s/containers", working_directory); + + d = opendir(containers_path); + if (!d) { + fprintf(stderr, "Failed to open directory '%s'\n", containers_path); + goto finish; + } + + while ((dir = readdir(d)) != NULL) { + char *container_workdir_path = malloc(strlen(containers_path) + strlen(dir->d_name) + 2); + if (!container_workdir_path) { + fprintf(stderr, "Failed to allocate memory for container workdir path\n"); + goto finish; + } + + strcpy(container_workdir_path, containers_path); + strcat(container_workdir_path, "/"); + strcat(container_workdir_path, dir->d_name); + + if (rm_rf(container_workdir_path)) { + fprintf(stderr, "Failed to remove container workdir '%s'\n", container_workdir_path); + free(container_workdir_path); + goto finish; + } + + free(container_workdir_path); + } + + ret = 0; + +finish: + if (d) { + closedir(d); + } + + free(containers_path); + + return ret; +} + struct ocre_context *ocre_create_context(const char *workdir) { int rc; @@ -58,6 +111,8 @@ struct ocre_context *ocre_create_context(const char *workdir) goto error; } + delete_container_workdirs(context->working_directory); + rc = pthread_mutex_init(&context->mutex, NULL); if (rc) { LOG_ERR("Failed to initialize context mutex: rc=%d", rc); @@ -186,11 +241,11 @@ struct ocre_container *ocre_context_create_container(struct ocre_context *contex memset(node, 0, sizeof(struct container_node)); - /* Build the absolute path to the image */ + /* Build the full path to the image */ image_path = malloc(strlen(context->working_directory) + strlen("/images/") + strlen(image) + 1); if (!image_path) { - LOG_ERR("Failed to allocate memory for absolute path"); + LOG_ERR("Failed to allocate memory for image path"); goto error; } @@ -200,19 +255,20 @@ struct ocre_container *ocre_context_create_container(struct ocre_context *contex // TODO: check if image exists - /* Build the absolute path to the working dir and create it */ + /* Build the path to the working dir and create it */ if (arguments && string_array_lookup(arguments->capabilities, "filesystem")) { - container_workdir = - malloc(strlen(context->working_directory) + strlen("/containers/") + strlen(container_id) + 1); + container_workdir = malloc(strlen(context->working_directory) + strlen("/containers/") + + strlen(computed_container_id) + 1); if (!container_workdir) { LOG_ERR("Failed to allocate memory for working directory"); goto error; } snprintf(container_workdir, - strlen(context->working_directory) + strlen("/containers/") + strlen(container_id) + 1, - "%s/containers/%s", context->working_directory, container_id); + strlen(context->working_directory) + strlen("/containers/") + strlen(computed_container_id) + + 1, + "%s/containers/%s", context->working_directory, computed_container_id); rc = mkdir(container_workdir, 0755); if (rc) { @@ -223,7 +279,8 @@ struct ocre_container *ocre_context_create_container(struct ocre_context *contex /* Create the container */ - container = ocre_container_create(image_path, container_workdir, runtime, computed_container_id, detached, arguments); + container = ocre_container_create(image_path, container_workdir, runtime, computed_container_id, detached, + arguments); if (!container) { LOG_ERR("Failed to create container %s: errno=%d", computed_container_id, errno); goto error; From 576a9141eec12de39160e63d014b19beff9dbe66 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 9 Dec 2025 20:53:45 +0100 Subject: [PATCH 063/234] feat(runner/wamr): handle dir mounts and filesystem We need to add the mounts according to the parameters passed to create. Signed-off-by: Marco Casaroli --- src/runtime/wamr/wamr.c | 116 ++++++++++++++++++++++++++++++++-------- 1 file changed, 94 insertions(+), 22 deletions(-) diff --git a/src/runtime/wamr/wamr.c b/src/runtime/wamr/wamr.c index 67213b55..9a71c97b 100644 --- a/src/runtime/wamr/wamr.c +++ b/src/runtime/wamr/wamr.c @@ -171,15 +171,19 @@ static int runtime_deinit(void) static void *instance_create(const char *img_path, const char *workdir, size_t stack_size, size_t heap_size, const char **capabilities, const char **argv, const char **envp, const char **mounts) { + struct wamr_context *context = NULL; + char **dir_map_list = NULL; + size_t dir_map_list_len = 0; + if (!img_path) { LOG_ERR("Invalid arguments"); return NULL; } - struct wamr_context *context = malloc(sizeof(struct wamr_context)); + context = malloc(sizeof(struct wamr_context)); if (!context) { LOG_ERR("Failed to allocate memory for context size=%zu errno=%d", sizeof(struct wamr_context), errno); - return NULL; + goto error; } memset(context, 0, sizeof(struct wamr_context)); @@ -209,21 +213,21 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s context->argv = malloc(sizeof(char *) * (argc + 2)); if (!context->argv) { LOG_ERR("Failed to allocate memory for argv"); - goto error_context; + goto error; } memset(context->argv, 0, sizeof(char *) * (argc + 2)); context->argv[0] = strdup(img_path); if (!context->argv[0]) { - goto error_argv; + goto error; } int i; for (i = 0; i < argc; i++) { - context->argv[i + 1] = strdup(argv[i]); + context->argv[i + 1] = (char *)argv[i]; if (!context->argv[i + 1]) { - goto error_argv; + goto error; } } @@ -238,7 +242,7 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s context->buffer = ocre_load_file(img_path, &context->size); if (!context->buffer) { LOG_ERR("Failed to load wasm program into buffer errno=%d", errno); - goto error_argv; + goto error; } LOG_INF("Buffer loaded successfully: %p", context->buffer); @@ -247,12 +251,9 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s sizeof(context->error_buf)); if (!context->module) { LOG_ERR("Failed to load module: %s", context->error_buf); - goto error_buffer; + goto error; } - const char **dir_map_list = NULL; - size_t dir_map_list_len = 0; - /* Process capabilities */ for (const char **cap = capabilities; cap && *cap; cap++) { @@ -270,19 +271,65 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s sizeof(ns_lookup_pool) / sizeof(ns_lookup_pool[0])); LOG_INF("Network capability enabled"); - } else if (!strcmp(*cap, "filesystem")) { -#ifdef PICO_RP2350 - static const char *dir_map[] = {"/::/lfs/cfs"}; // TODO: fix this -#else - static const char *dir_map[] = {"/::/"}; // TODO: fix this -#endif - dir_map_list = dir_map; - dir_map_list_len = sizeof(dir_map) / sizeof(dir_map[0]); + } else if (!strcmp(*cap, "filesystem") && workdir) { + dir_map_list = malloc(sizeof(char *)); + if (!dir_map_list) { + LOG_ERR("Failed to allocate memory for dir_map_list"); + goto error; + } + + memset(dir_map_list, 0, sizeof(char *)); + + dir_map_list[0] = malloc(strlen("/::") + strlen(workdir) + 1); + if (!dir_map_list[0]) { + LOG_ERR("Failed to allocate memory for dir_map_list[0]"); + free(dir_map_list); + goto error; + } + + sprintf(dir_map_list[0], "/::%s", workdir); + + dir_map_list_len++; + LOG_INF("Filesystem capability enabled"); } } - wasm_runtime_set_wasi_args(context->module, NULL, 0, dir_map_list, dir_map_list_len, envp, envn, context->argv, + /* Add the mounts to the directory map list */ + + for (const char **mount = mounts; mount && *mount; mount++) { + + /* Need to insert the extra ':' */ + + dir_map_list[dir_map_list_len] = malloc(strlen(*mount) + 2); + if (!dir_map_list[dir_map_list_len]) { + LOG_ERR("Failed to allocate memory for dir_map_list[%zu]", dir_map_list_len); + goto error; + } + + char *src_colon = strchr(*mount, ':'); + if (!src_colon) { + LOG_ERR("Invalid mount format: %s", *mount); + goto error; + } + + strcpy(dir_map_list[dir_map_list_len], *mount); + + char *dst_colon = strchr(dir_map_list[dir_map_list_len], ':'); + if (!dst_colon) { + LOG_ERR("Invalid mount format: %s", *mount); + goto error; + } + + sprintf(dst_colon+1, ":%s", src_colon+1); + + LOG_INF("Enabled mount: %s", dir_map_list[dir_map_list_len]); + + dir_map_list_len++; + + } + + wasm_runtime_set_wasi_args(context->module, NULL, 0, (const char **)dir_map_list, dir_map_list_len, envp, envn, context->argv, argc + 1); context->module_inst = wasm_runtime_instantiate(context->module, stack_size, heap_size, context->error_buf, @@ -323,12 +370,37 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s context->buffer = NULL; error_argv: - /* Only free what we allocated */ free(context->argv[0]); free(context->argv); -error_context: +error: + + for (char **dir_map = dir_map_list; dir_map && *dir_map; dir_map++) { + free(*dir_map); + } + + free(dir_map_list); + + if (context) { + if (context->module) { + wasm_runtime_unload(context->module); + } + + if (context->buffer) { + ocre_unload_file(context->buffer, context->size); + context->buffer = NULL; + } + + /* Only free what we allocated */ + + if (context->argv) { + free(context->argv[0]); + } + + free(context->argv); + } + free(context); return NULL; From e34c7e3fdd1acf2fe1bda59d282e3286c9b2b438 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 9 Dec 2025 20:55:53 +0100 Subject: [PATCH 064/234] feat(file_mmap): silently handle NULL pointer Like free, we want to just ignore if we get called with NULL. Signed-off-by: Marco Casaroli --- src/platform/posix/file_mmap.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/platform/posix/file_mmap.c b/src/platform/posix/file_mmap.c index 98bbe1c8..a9eb4b64 100644 --- a/src/platform/posix/file_mmap.c +++ b/src/platform/posix/file_mmap.c @@ -78,6 +78,10 @@ void *ocre_load_file(const char *path, size_t *size) int ocre_unload_file(void *buffer, size_t size) { + if (!buffer) { + return 0; + } + if (munmap(buffer, size)) { int save_errno = errno; LOG_ERR("Failed to munmap file errno=%d", save_errno); From 9b89a4ab1e87938426185038487f37a9761af4c5 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 10 Dec 2025 09:12:08 +0100 Subject: [PATCH 065/234] feat(container): handle pause/unpause Even that the runtime does not yet support it, we have the support in Ocre. Signed-off-by: Marco Casaroli --- src/ocre/container.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/ocre/container.c b/src/ocre/container.c index 22a101a3..a8fd55b8 100644 --- a/src/ocre/container.c +++ b/src/ocre/container.c @@ -488,6 +488,13 @@ int ocre_container_pause(struct ocre_container *container) ret = container->runtime->pause(container->runtime_context); + if (ret) { + LOG_ERR("Failed to pause container '%s': rc=%d", container->id, ret); + goto unlock_mutex; + } + + container->status = OCRE_CONTAINER_STATUS_PAUSED; + unlock_mutex: rc = pthread_mutex_unlock(&container->mutex); if (rc) { @@ -526,6 +533,13 @@ int ocre_container_unpause(struct ocre_container *container) ret = container->runtime->unpause(container->runtime_context); + if (ret) { + LOG_ERR("Failed to unpause container '%s': rc=%d", container->id, ret); + goto unlock_mutex; + } + + container->status = OCRE_CONTAINER_STATUS_RUNNING; + unlock_mutex: rc = pthread_mutex_unlock(&container->mutex); if (rc) { From 492b67d9db1bf06fba6abd561fb05cf1faaf38f5 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 10 Dec 2025 09:12:50 +0100 Subject: [PATCH 066/234] feat(shell): pause/unpause Forward these commands to ocre. Signed-off-by: Marco Casaroli --- src/shell/CMakeLists.txt | 2 ++ src/shell/container.c | 20 ++++++++++--------- src/shell/container/pause.c | 37 +++++++++++++++++++++++++++++++++++ src/shell/container/pause.h | 3 +++ src/shell/container/unpause.c | 37 +++++++++++++++++++++++++++++++++++ src/shell/container/unpause.h | 3 +++ src/shell/shell.c | 8 ++++++-- 7 files changed, 99 insertions(+), 11 deletions(-) create mode 100644 src/shell/container/pause.c create mode 100644 src/shell/container/pause.h create mode 100644 src/shell/container/unpause.c create mode 100644 src/shell/container/unpause.h diff --git a/src/shell/CMakeLists.txt b/src/shell/CMakeLists.txt index 7e282934..6c7ae764 100644 --- a/src/shell/CMakeLists.txt +++ b/src/shell/CMakeLists.txt @@ -13,10 +13,12 @@ target_sources(OcreShell container/create.c container/inspect.c container/kill.c + container/pause.c container/ps.c container/rm.c container/start.c container/stop.c + container/unpause.c container/wait.c sha256/sha256.c ) diff --git a/src/shell/container.c b/src/shell/container.c index a392e231..e342d64d 100644 --- a/src/shell/container.c +++ b/src/shell/container.c @@ -5,14 +5,16 @@ #include "command.h" +#include "container/inspect.h" +#include "container/create.h" +#include "container/kill.h" +#include "container/pause.h" +#include "container/ps.h" +#include "container/rm.h" #include "container/start.h" #include "container/stop.h" -#include "container/rm.h" -#include "container/kill.h" -#include "container/inspect.h" +#include "container/unpause.h" #include "container/wait.h" -#include "container/ps.h" -#include "container/create.h" static int print_usage(struct ocre_context *ctx, char *argv0, int argc, char **argv) { @@ -25,8 +27,8 @@ static int print_usage(struct ocre_context *ctx, char *argv0, int argc, char **a fprintf(stderr, " stop Stop a running or paused container\n"); fprintf(stderr, " kill Kill a running or paused container\n"); // fprintf(stderr, " restart Restart a running, stopped, or paused container\n"); - // fprintf(stderr, " pause Pause a running container\n"); - // fprintf(stderr, " unpause Resume a paused container\n"); + fprintf(stderr, " pause Pause a running container\n"); + fprintf(stderr, " unpause Resume a paused container\n"); fprintf(stderr, " inspect Display detailed information about a container\n"); fprintf(stderr, " wait Wait for a container to exit\n"); fprintf(stderr, " ps List containers\n"); @@ -42,8 +44,8 @@ static const struct ocre_command commands[] = { {"stop", cmd_container_stop}, {"kill", cmd_container_kill}, // {"restart", cmd_container_restart}, - // {"pause", cmd_container_pause}, - // {"unpause", cmd_container_unpause}, + {"pause", cmd_container_pause}, + {"unpause", cmd_container_unpause}, {"inspect", cmd_container_inspect}, {"wait", cmd_container_wait}, {"ps", cmd_container_ps}, diff --git a/src/shell/container/pause.c b/src/shell/container/pause.c new file mode 100644 index 00000000..7a47bd3a --- /dev/null +++ b/src/shell/container/pause.c @@ -0,0 +1,37 @@ +#include +#include + +#include + +#include "../command.h" + +static int usage(const char *argv0) +{ + fprintf(stderr, "Usage: %s container pause CONTAINER\n", argv0); + fprintf(stderr, "\nPauses a container in the OCRE context.\n"); + return -1; +} + +int cmd_container_pause(struct ocre_context *ctx, char *argv0, int argc, char **argv) +{ + if (argc == 2) { + + struct ocre_container *container = ocre_context_get_container_by_id(ctx, argv[1]); + if (!container) { + fprintf(stderr, "Failed to get container '%s'\n", argv[1]); + return -1; + } + + if (ocre_container_get_status(container) != OCRE_CONTAINER_STATUS_RUNNING) { + fprintf(stderr, "Container '%s' is not running\n", argv[1]); + return -1; + } + + return ocre_container_pause(container); + } else { + fprintf(stderr, "'%s container pause' requires exactly one argument\n\n", argv0); + return usage(argv0); + } + + return 0; +} diff --git a/src/shell/container/pause.h b/src/shell/container/pause.h new file mode 100644 index 00000000..1b8cfc17 --- /dev/null +++ b/src/shell/container/pause.h @@ -0,0 +1,3 @@ +#include + +int cmd_container_pause(struct ocre_context *ctx, char *argv0, int argc, char **argv); diff --git a/src/shell/container/unpause.c b/src/shell/container/unpause.c new file mode 100644 index 00000000..1acdaa57 --- /dev/null +++ b/src/shell/container/unpause.c @@ -0,0 +1,37 @@ +#include +#include + +#include + +#include "../command.h" + +static int usage(const char *argv0) +{ + fprintf(stderr, "Usage: %s container unpause CONTAINER\n", argv0); + fprintf(stderr, "\nUnpauses a container in the OCRE context.\n"); + return -1; +} + +int cmd_container_unpause(struct ocre_context *ctx, char *argv0, int argc, char **argv) +{ + if (argc == 2) { + + struct ocre_container *container = ocre_context_get_container_by_id(ctx, argv[1]); + if (!container) { + fprintf(stderr, "Failed to get container '%s'\n", argv[1]); + return -1; + } + + if (ocre_container_get_status(container) != OCRE_CONTAINER_STATUS_PAUSED) { + fprintf(stderr, "Container '%s' is not paused\n", argv[1]); + return -1; + } + + return ocre_container_unpause(container); + } else { + fprintf(stderr, "'%s container unpause' requires exactly one argument\n\n", argv0); + return usage(argv0); + } + + return 0; +} diff --git a/src/shell/container/unpause.h b/src/shell/container/unpause.h new file mode 100644 index 00000000..aadbf1f2 --- /dev/null +++ b/src/shell/container/unpause.h @@ -0,0 +1,3 @@ +#include + +int cmd_container_unpause(struct ocre_context *ctx, char *argv0, int argc, char **argv); diff --git a/src/shell/shell.c b/src/shell/shell.c index ad6d77e3..26d04946 100644 --- a/src/shell/shell.c +++ b/src/shell/shell.c @@ -10,9 +10,11 @@ #include "image/pull.h" #include "container.h" #include "container/kill.h" +#include "container/pause.h" #include "container/ps.h" #include "container/rm.h" #include "container/start.h" +#include "container/unpause.h" #include "container/inspect.h" #include "container/stop.h" #include "container/wait.h" @@ -41,8 +43,8 @@ static int print_usage(struct ocre_context *ctx, char *argv0, int argc, char **a fprintf(stderr, " stop container stop\n"); fprintf(stderr, " kill container kill\n"); // fprintf(stderr, " restart container restart\n"); - // fprintf(stderr, " pause container pause\n"); - // fprintf(stderr, " unpause container unpause\n"); + fprintf(stderr, " pause container pause\n"); + fprintf(stderr, " unpause container unpause\n"); fprintf(stderr, " rm container rm\n"); fprintf(stderr, " images image ls\n"); fprintf(stderr, " pull image pull\n"); @@ -62,6 +64,8 @@ static const struct ocre_command commands[] = { {"start", cmd_container_start}, {"stop", cmd_container_stop}, {"kill", cmd_container_kill}, + {"pause", cmd_container_pause}, + {"unpause", cmd_container_unpause}, {"rm", cmd_container_rm}, // image shortcuts {"images", cmd_image_ls}, From d7407f09e86bdc6df47632b0417105785abb63f3 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 10 Dec 2025 09:19:38 +0100 Subject: [PATCH 067/234] fix(shell/create): clean up properly on error We cannot return NULL. We should go to cleanup error so we free the allocated arrays. Signed-off-by: Marco Casaroli --- src/shell/container/create.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/shell/container/create.c b/src/shell/container/create.c index 654a0a2a..039e7758 100644 --- a/src/shell/container/create.c +++ b/src/shell/container/create.c @@ -94,13 +94,13 @@ int cmd_container_create_run(struct ocre_context *ctx, char *argv0, int argc, ch if (optarg[0] != '/') { fprintf(stderr, "Invalid mount format: '%s': source must be absolute path", optarg); - return NULL; + goto cleanup; } char *dst = strchr(optarg, ':'); if (!dst) { fprintf(stderr, "Invalid mount format: '%s': must be :", optarg); - return NULL; + goto cleanup; } dst++; @@ -108,12 +108,12 @@ int cmd_container_create_run(struct ocre_context *ctx, char *argv0, int argc, ch if (dst[0] != '/') { fprintf(stderr, "Invalid mount format: '%s': destination must be absolute path", optarg); - return NULL; + goto cleanup; } if (dst[1] == '\0') { fprintf(stderr, "Invalid mount format: '%s': destination must not be '/'", optarg); - return NULL; + goto cleanup; } mounts = realloc(mounts, sizeof(char *) * (mounts_count + 1)); @@ -133,7 +133,6 @@ int cmd_container_create_run(struct ocre_context *ctx, char *argv0, int argc, ch case '?': { fprintf(stderr, "Invalid option '-%c'\n", optopt); goto cleanup; - break; } } } From 02efd8e379b43ed85a8f0233416dd67d8d70c68f Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 10 Dec 2025 09:21:40 +0100 Subject: [PATCH 068/234] feat(container): handle stop Even if we don't support it in the runtime, yet, we can handle it for completeness. Signed-off-by: Marco Casaroli --- src/ocre/container.c | 33 +++++++++++++++++++++++++++++++++ src/ocre/include/ocre/ocre.h | 2 +- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/ocre/container.c b/src/ocre/container.c index a8fd55b8..4adec47c 100644 --- a/src/ocre/container.c +++ b/src/ocre/container.c @@ -426,6 +426,39 @@ ocre_container_status_t ocre_container_get_status(struct ocre_container *contain return status; } +int ocre_container_stop(struct ocre_container *container) +{ + int ret = -1; + if (!container) { + LOG_ERR("Invalid container"); + return -1; + } + + int rc; + rc = pthread_mutex_lock(&container->mutex); + if (rc) { + LOG_ERR("Failed to lock mutex: rc=%d", rc); + return -1; + } + + if (container->status != OCRE_CONTAINER_STATUS_RUNNING) { + LOG_ERR("Container '%s' is not running", container->id); + goto unlock_mutex; + } + + LOG_INF("Sending stop signal to container '%s'", container->id); + + ret = container->runtime->stop(container->runtime_context); + +unlock_mutex: + rc = pthread_mutex_unlock(&container->mutex); + if (rc) { + LOG_ERR("Failed to unlock mutex: rc=%d", rc); + } + + return ret; +} + int ocre_container_kill(struct ocre_container *container) { int ret = -1; diff --git a/src/ocre/include/ocre/ocre.h b/src/ocre/include/ocre/ocre.h index 276f2f88..5eb6b282 100644 --- a/src/ocre/include/ocre/ocre.h +++ b/src/ocre/include/ocre/ocre.h @@ -67,7 +67,7 @@ char *ocre_container_get_image_a(const struct ocre_container *container); // int ocre_container_get_info(struct ocre_container *container, struct container_info *info); int ocre_container_pause(struct ocre_container *container); int ocre_container_unpause(struct ocre_container *container); -// int ocre_container_stop(struct ocre_container *container); +int ocre_container_stop(struct ocre_container *container); int ocre_container_kill(struct ocre_container *container); int ocre_container_wait(struct ocre_container *container, int *status); From fce1b2fbd3f4c4b7965a59400550985ad8a2ca8d Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 10 Dec 2025 09:22:22 +0100 Subject: [PATCH 069/234] feat(shell): container stop We forward these calls to Ocre. Signed-off-by: Marco Casaroli --- src/shell/container/stop.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/shell/container/stop.c b/src/shell/container/stop.c index 5a2e758a..6b87c970 100644 --- a/src/shell/container/stop.c +++ b/src/shell/container/stop.c @@ -14,8 +14,19 @@ static int usage(const char *argv0) int cmd_container_stop(struct ocre_context *ctx, char *argv0, int argc, char **argv) { - if (argc == 1) { - printf("Stopping container '%s'...\n", argv[1]); + if (argc == 2) { + struct ocre_container *container = ocre_context_get_container_by_id(ctx, argv[1]); + if (!container) { + fprintf(stderr, "Failed to get container '%s'\n", argv[1]); + return -1; + } + + if (ocre_container_get_status(container) != OCRE_CONTAINER_STATUS_RUNNING) { + fprintf(stderr, "Container '%s' is not running\n", argv[1]); + return -1; + } + + return ocre_container_stop(container); } else { fprintf(stderr, "'%s container stop' requires exactly one argument\n\n", argv0); return usage(argv0); From 62b70f91559b33983bcb4b4fe8900d66dda3e9dc Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 10 Dec 2025 09:26:42 +0100 Subject: [PATCH 070/234] fix(shell): disable unsupported commands. These commands will be available in the future. We disable them now to avoid confusion about unsupported feature. Signed-off-by: Marco Casaroli --- src/shell/container.c | 16 ++++++---------- src/shell/container/inspect.c | 25 ------------------------- src/shell/container/inspect.h | 3 --- src/shell/shell.c | 14 ++++++-------- 4 files changed, 12 insertions(+), 46 deletions(-) delete mode 100644 src/shell/container/inspect.c delete mode 100644 src/shell/container/inspect.h diff --git a/src/shell/container.c b/src/shell/container.c index e342d64d..07edba17 100644 --- a/src/shell/container.c +++ b/src/shell/container.c @@ -24,12 +24,10 @@ static int print_usage(struct ocre_context *ctx, char *argv0, int argc, char **a fprintf(stderr, " run Created and starts a new container\n"); fprintf(stderr, " create Create a new container\n"); fprintf(stderr, " start Start a container\n"); - fprintf(stderr, " stop Stop a running or paused container\n"); + // fprintf(stderr, " stop Stop a running or paused container\n"); fprintf(stderr, " kill Kill a running or paused container\n"); - // fprintf(stderr, " restart Restart a running, stopped, or paused container\n"); - fprintf(stderr, " pause Pause a running container\n"); - fprintf(stderr, " unpause Resume a paused container\n"); - fprintf(stderr, " inspect Display detailed information about a container\n"); + // fprintf(stderr, " pause Pause a running container\n"); + // fprintf(stderr, " unpause Resume a paused container\n"); fprintf(stderr, " wait Wait for a container to exit\n"); fprintf(stderr, " ps List containers\n"); fprintf(stderr, " rm Remove a stopped container\n"); @@ -41,12 +39,10 @@ static const struct ocre_command commands[] = { {"run", cmd_container_create_run}, {"create", cmd_container_create_run}, {"start", cmd_container_start}, - {"stop", cmd_container_stop}, + // {"stop", cmd_container_stop}, {"kill", cmd_container_kill}, - // {"restart", cmd_container_restart}, - {"pause", cmd_container_pause}, - {"unpause", cmd_container_unpause}, - {"inspect", cmd_container_inspect}, + // {"pause", cmd_container_pause}, + // {"unpause", cmd_container_unpause}, {"wait", cmd_container_wait}, {"ps", cmd_container_ps}, {"rm", cmd_container_rm}, diff --git a/src/shell/container/inspect.c b/src/shell/container/inspect.c deleted file mode 100644 index 6f3f6c7a..00000000 --- a/src/shell/container/inspect.c +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include - -#include - -#include "../command.h" - -static int usage(const char *argv0) -{ - fprintf(stderr, "Usage: %s container status CONTAINER\n", argv0); - fprintf(stderr, "\nChecks the status of a container in the OCRE context.\n"); - return -1; -} - -int cmd_container_inspect(struct ocre_context *ctx, char *argv0, int argc, char **argv) -{ - if (argc == 1) { - printf("Getting status of container '%s'...\n", argv[1]); - } else { - fprintf(stderr, "'%s container status' requires exactly one argument\n\n", argv0); - return usage(argv0); - } - - return 0; -} diff --git a/src/shell/container/inspect.h b/src/shell/container/inspect.h deleted file mode 100644 index 2b7cf92e..00000000 --- a/src/shell/container/inspect.h +++ /dev/null @@ -1,3 +0,0 @@ -#include - -int cmd_container_inspect(struct ocre_context *ctx, char *argv0, int argc, char **argv); diff --git a/src/shell/shell.c b/src/shell/shell.c index 26d04946..47951cd9 100644 --- a/src/shell/shell.c +++ b/src/shell/shell.c @@ -15,7 +15,6 @@ #include "container/rm.h" #include "container/start.h" #include "container/unpause.h" -#include "container/inspect.h" #include "container/stop.h" #include "container/wait.h" #include "container/create.h" @@ -40,11 +39,10 @@ static int print_usage(struct ocre_context *ctx, char *argv0, int argc, char **a fprintf(stderr, " create container create\n"); fprintf(stderr, " run container run\n"); fprintf(stderr, " start container start\n"); - fprintf(stderr, " stop container stop\n"); + // fprintf(stderr, " stop container stop\n"); fprintf(stderr, " kill container kill\n"); - // fprintf(stderr, " restart container restart\n"); - fprintf(stderr, " pause container pause\n"); - fprintf(stderr, " unpause container unpause\n"); + // fprintf(stderr, " pause container pause\n"); + // fprintf(stderr, " unpause container unpause\n"); fprintf(stderr, " rm container rm\n"); fprintf(stderr, " images image ls\n"); fprintf(stderr, " pull image pull\n"); @@ -62,10 +60,10 @@ static const struct ocre_command commands[] = { {"create", cmd_container_create_run}, {"run", cmd_container_create_run}, {"start", cmd_container_start}, - {"stop", cmd_container_stop}, + // {"stop", cmd_container_stop}, {"kill", cmd_container_kill}, - {"pause", cmd_container_pause}, - {"unpause", cmd_container_unpause}, + // {"pause", cmd_container_pause}, + // {"unpause", cmd_container_unpause}, {"rm", cmd_container_rm}, // image shortcuts {"images", cmd_image_ls}, From 4772f9d07a5c34f7095ca8b00a4c6c7285cb7be6 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 10 Dec 2025 14:10:00 +0100 Subject: [PATCH 071/234] fix(shell): remove inspect Signed-off-by: Marco Casaroli --- src/shell/CMakeLists.txt | 1 - src/shell/container.c | 1 - 2 files changed, 2 deletions(-) diff --git a/src/shell/CMakeLists.txt b/src/shell/CMakeLists.txt index 6c7ae764..9478ce9d 100644 --- a/src/shell/CMakeLists.txt +++ b/src/shell/CMakeLists.txt @@ -11,7 +11,6 @@ target_sources(OcreShell image/rm.c container.c container/create.c - container/inspect.c container/kill.c container/pause.c container/ps.c diff --git a/src/shell/container.c b/src/shell/container.c index 07edba17..0680af2f 100644 --- a/src/shell/container.c +++ b/src/shell/container.c @@ -5,7 +5,6 @@ #include "command.h" -#include "container/inspect.h" #include "container/create.h" #include "container/kill.h" #include "container/pause.h" From e414dd849af4430d39ea2f3fe37b7f1561d40c60 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 10 Dec 2025 14:11:07 +0100 Subject: [PATCH 072/234] build: handle SDK sample containters in state information Signed-off-by: Marco Casaroli --- cmake/sample_containers.cmake | 13 +++++++++++++ cmake/state_information.cmake | 19 +++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 cmake/sample_containers.cmake diff --git a/cmake/sample_containers.cmake b/cmake/sample_containers.cmake new file mode 100644 index 00000000..91b1ca45 --- /dev/null +++ b/cmake/sample_containers.cmake @@ -0,0 +1,13 @@ +include(ExternalProject) + +ExternalProject_Add( + OcreSampleContainers + PREFIX "${CMAKE_CURRENT_BINARY_DIR}/OcreSampleContainers" + BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/OcreSampleContainers/build" + BUILD_ALWAYS TRUE + INSTALL_COMMAND "" + SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../ocre-sdk" + CMAKE_ARGS "-DWAMR_ROOT_DIR=${CMAKE_CURRENT_LIST_DIR}/../wasm-micro-runtime" +) + +set(OCRE_SAMPLE_CONTAINER_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/OcreSampleContainers/build") diff --git a/cmake/state_information.cmake b/cmake/state_information.cmake index e6d2974c..a9d2eebb 100644 --- a/cmake/state_information.cmake +++ b/cmake/state_information.cmake @@ -9,9 +9,28 @@ if (OCRE_INPUT_FILE_NAME) list(APPEND OCRE_PRELOADED_IMAGES ${OCRE_INPUT_FILE_NAME}) endif() +# populate user provided preloaded images foreach(image IN ITEMS ${OCRE_PRELOADED_IMAGES}) message(STATUS "Adding '${image}' to preloaded images") file(COPY ${image} DESTINATION var/lib/ocre/images/) cmake_path(GET image FILENAME filename) list(APPEND OCRE_IMAGES ${CMAKE_CURRENT_BINARY_DIR}/var/lib/ocre/images/${filename}) endforeach() + +# populate SDK provided sample images +foreach(image IN ITEMS ${OCRE_SDK_PRELOADED_IMAGES}) + message(STATUS "Adding '${image}' to preloaded images") + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/var/lib/ocre/images/${image} + COMMAND ${CMAKE_COMMAND} -E copy + ${OCRE_SAMPLE_CONTAINER_LOCATION}/${image} + ${CMAKE_CURRENT_BINARY_DIR}/var/lib/ocre/images/${image} + DEPENDS OcreSampleContainers + ) + cmake_path(GET image FILENAME filename) + list(APPEND OCRE_IMAGES ${CMAKE_CURRENT_BINARY_DIR}/var/lib/ocre/images/${filename}) +endforeach() + +add_custom_target(OcrePreloadedImages + DEPENDS ${OCRE_IMAGES} +) From 9015d7017b15565cd4ec8c55a2562cbf0ca02816 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 10 Dec 2025 14:11:36 +0100 Subject: [PATCH 073/234] feat(samples/demo): add sample containers to build Signed-off-by: Marco Casaroli --- src/samples/demo/demo_containers.cmake | 10 ++++++++++ src/samples/demo/posix/CMakeLists.txt | 5 +++++ src/samples/demo/zephyr/CMakeLists.txt | 9 +++++++++ 3 files changed, 24 insertions(+) create mode 100644 src/samples/demo/demo_containers.cmake diff --git a/src/samples/demo/demo_containers.cmake b/src/samples/demo/demo_containers.cmake new file mode 100644 index 00000000..938d1a03 --- /dev/null +++ b/src/samples/demo/demo_containers.cmake @@ -0,0 +1,10 @@ +list(APPEND OCRE_SDK_PRELOADED_IMAGES + "hello-world.wasm" + "blinky.wasm" + "subscriber.wasm" + "publisher.wasm" + "filesystem.wasm" + "filesystem-full.wasm" + "webserver.wasm" + "webserver-complex.wasm" +) diff --git a/src/samples/demo/posix/CMakeLists.txt b/src/samples/demo/posix/CMakeLists.txt index fd03e014..e13656c7 100644 --- a/src/samples/demo/posix/CMakeLists.txt +++ b/src/samples/demo/posix/CMakeLists.txt @@ -17,3 +17,8 @@ target_link_libraries(ocre_demo PRIVATE -lpthread ) + +add_dependencies(ocre_demo + OcreSampleContainers + OcrePreloadedImages +) diff --git a/src/samples/demo/zephyr/CMakeLists.txt b/src/samples/demo/zephyr/CMakeLists.txt index 507015f8..2997f0f5 100644 --- a/src/samples/demo/zephyr/CMakeLists.txt +++ b/src/samples/demo/zephyr/CMakeLists.txt @@ -6,6 +6,10 @@ cmake_minimum_required(VERSION 3.20.0) # comment out to use the ocre module provided by Zephyr list(APPEND ZEPHYR_EXTRA_MODULES ${CMAKE_CURRENT_LIST_DIR}/../../../..) +include(../demo_containers.cmake) + +include(../../../../cmake/sample_containers.cmake) + find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project (ocre_sample_mini) @@ -19,3 +23,8 @@ target_link_libraries(app PUBLIC OcreCore ) + +add_dependencies(app + OcrePreloadedImages + OcreSampleContainers +) From c8c9244c39a95bd056c8a519fa2c530f8e51c8ed Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 10 Dec 2025 14:28:12 +0100 Subject: [PATCH 074/234] build: handle sample images and state information Signed-off-by: Marco Casaroli --- CMakeLists.txt | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d5574913..fd13b6af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,8 +14,7 @@ set(CMAKE_CXX_STANDARD 17) set(WAMR_BUILD_PLATFORM linux) # set(WAMR_BUILD_PLATFORM darwin) -# /var/lib/ocre directory -include (cmake/state_information.cmake) + # core add_subdirectory(src/ocre) @@ -34,4 +33,19 @@ add_subdirectory(src/platform/posix) # samples add_subdirectory(src/samples/mini/posix) add_subdirectory(src/samples/demo/posix) + +include (src/samples/demo/demo_containers.cmake) + +# TODO move these to testing +list(APPEND OCRE_SDK_PRELOADED_IMAGES + "return0.wasm" + "return1.wasm" + "sleep_5_return_0.wasm" +) + +include (cmake/sample_containers.cmake) + +# /var/lib/ocre directory +include (cmake/state_information.cmake) + add_subdirectory(src/samples/bash_runtime/posix) From 1f8c38cb1c621bff97adf65a16a84790ef716f3a Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 10 Dec 2025 14:43:24 +0100 Subject: [PATCH 075/234] chore(gitignore): handle hidden files It is safer to ignore all hidden files except the ones we like to keep. Signed-off-by: Marco Casaroli --- .gitignore | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 44bc6dde..e5b4b204 100644 --- a/.gitignore +++ b/.gitignore @@ -32,15 +32,9 @@ dist/ target/ dist/ -# JetBrains IDE -.idea/ - # Unit test reports TEST*.xml -# Generated by MacOS -.DS_Store - # Generated by Windows Thumbs.db @@ -57,11 +51,15 @@ Thumbs.db *.mov *.wmv -# VS Code IDE -.vscode/ # Generated by VS settings.json -.cache/ - src/ocre/commit_id.h + +# hidden files +.* +!.gitignore +!/.gitmodules +!/.github +!.devcontainer +!.ckang-format From d0e8d057e8accca01878f0584cec8aa85f5d77d4 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 10 Dec 2025 14:46:51 +0100 Subject: [PATCH 076/234] chore: remove .vscode Signed-off-by: Marco Casaroli --- .vscode/launch.json | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 27dd2bd9..00000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "C++ Launch", - "type": "cppdbg", - "request": "launch", - "program": "${workspaceFolder}/build/src/samples/bash_runtime/posix/ocre_bash", - "cwd": "${workspaceFolder}/build", - "MIMode": "lldb" - } - ] -} \ No newline at end of file From 7db11ba4b2b60ae561f5c1d2c77b3bf94aa13dec Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 10 Dec 2025 18:29:59 +0100 Subject: [PATCH 077/234] build: improve handling of sample images and state info We now rebuild ocre-sdk if images are specified for the sample or by the user. We use add_custom_target for cmake to handle the dependencies. If those files are updated in the system, or after the ocre-sdk rebuild, they will be copied again to state information directory. Signed-off-by: Marco Casaroli --- CMakeLists.txt | 21 +++------ cmake/sample_containers.cmake | 13 ----- cmake/state_information.cmake | 47 ++++++++++++------- src/ocre/CMakeLists.txt | 6 +++ .../posix/include/ocre/platform/config.h | 2 +- src/samples/demo/posix/CMakeLists.txt | 6 --- src/samples/demo/zephyr/CMakeLists.txt | 1 - src/samples/mini/posix/CMakeLists.txt | 1 - zephyr/storage_partition.cmake | 27 ++++++----- 9 files changed, 58 insertions(+), 66 deletions(-) delete mode 100644 cmake/sample_containers.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index fd13b6af..608a6618 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,14 @@ set(CMAKE_CXX_STANDARD 17) set(WAMR_BUILD_PLATFORM linux) # set(WAMR_BUILD_PLATFORM darwin) +include (src/samples/demo/demo_containers.cmake) +# TODO move these to testing +list(APPEND OCRE_SDK_PRELOADED_IMAGES + "return0.wasm" + "return1.wasm" + "sleep_5_return_0.wasm" +) # core add_subdirectory(src/ocre) @@ -34,18 +41,4 @@ add_subdirectory(src/platform/posix) add_subdirectory(src/samples/mini/posix) add_subdirectory(src/samples/demo/posix) -include (src/samples/demo/demo_containers.cmake) - -# TODO move these to testing -list(APPEND OCRE_SDK_PRELOADED_IMAGES - "return0.wasm" - "return1.wasm" - "sleep_5_return_0.wasm" -) - -include (cmake/sample_containers.cmake) - -# /var/lib/ocre directory -include (cmake/state_information.cmake) - add_subdirectory(src/samples/bash_runtime/posix) diff --git a/cmake/sample_containers.cmake b/cmake/sample_containers.cmake deleted file mode 100644 index 91b1ca45..00000000 --- a/cmake/sample_containers.cmake +++ /dev/null @@ -1,13 +0,0 @@ -include(ExternalProject) - -ExternalProject_Add( - OcreSampleContainers - PREFIX "${CMAKE_CURRENT_BINARY_DIR}/OcreSampleContainers" - BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/OcreSampleContainers/build" - BUILD_ALWAYS TRUE - INSTALL_COMMAND "" - SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../ocre-sdk" - CMAKE_ARGS "-DWAMR_ROOT_DIR=${CMAKE_CURRENT_LIST_DIR}/../wasm-micro-runtime" -) - -set(OCRE_SAMPLE_CONTAINER_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/OcreSampleContainers/build") diff --git a/cmake/state_information.cmake b/cmake/state_information.cmake index a9d2eebb..52aa0d3c 100644 --- a/cmake/state_information.cmake +++ b/cmake/state_information.cmake @@ -4,33 +4,44 @@ file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/var/lib/ocre/images) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/var/lib/ocre/volumes) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/var/lib/ocre/containers) +if(OCRE_SDK_PRELOADED_IMAGES) + include(ExternalProject) + ExternalProject_Add( + OcreSampleContainers + PREFIX "${CMAKE_CURRENT_BINARY_DIR}/OcreSampleContainers" + BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/OcreSampleContainers/build" + BUILD_ALWAYS TRUE + INSTALL_COMMAND "" + SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../ocre-sdk" + CMAKE_ARGS "-DWAMR_ROOT_DIR=${CMAKE_CURRENT_LIST_DIR}/../wasm-micro-runtime" + ) +endif() + if (OCRE_INPUT_FILE_NAME) - message(DEPRECATION "Adding '${OCRE_INPUT_FILE_NAME}' to preloaded images. Please use OCRE_PRELOADED_IMAGES instead.") + message(STATUS "Adding user provided '${OCRE_INPUT_FILE_NAME}' to preloaded images") list(APPEND OCRE_PRELOADED_IMAGES ${OCRE_INPUT_FILE_NAME}) endif() -# populate user provided preloaded images -foreach(image IN ITEMS ${OCRE_PRELOADED_IMAGES}) - message(STATUS "Adding '${image}' to preloaded images") - file(COPY ${image} DESTINATION var/lib/ocre/images/) - cmake_path(GET image FILENAME filename) - list(APPEND OCRE_IMAGES ${CMAKE_CURRENT_BINARY_DIR}/var/lib/ocre/images/${filename}) -endforeach() - # populate SDK provided sample images foreach(image IN ITEMS ${OCRE_SDK_PRELOADED_IMAGES}) - message(STATUS "Adding '${image}' to preloaded images") - add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/var/lib/ocre/images/${image} + message(STATUS "Adding sdk sample '${image}' to preloaded images") + add_custom_target(${image} COMMAND ${CMAKE_COMMAND} -E copy - ${OCRE_SAMPLE_CONTAINER_LOCATION}/${image} + ${CMAKE_CURRENT_BINARY_DIR}/OcreSampleContainers/build/${image} ${CMAKE_CURRENT_BINARY_DIR}/var/lib/ocre/images/${image} DEPENDS OcreSampleContainers ) - cmake_path(GET image FILENAME filename) - list(APPEND OCRE_IMAGES ${CMAKE_CURRENT_BINARY_DIR}/var/lib/ocre/images/${filename}) + list(APPEND OCRE_IMAGES ${image}) endforeach() -add_custom_target(OcrePreloadedImages - DEPENDS ${OCRE_IMAGES} -) +# populate user provided sample files +foreach(file IN ITEMS ${OCRE_PRELOADED_IMAGES}) + message(STATUS "Adding user provided '${file}' to preloaded images") + cmake_path(GET file FILENAME image) + add_custom_target(${image} + COMMAND ${CMAKE_COMMAND} -E copy + ${file} + ${CMAKE_CURRENT_BINARY_DIR}/var/lib/ocre/images/${image} + ) + list(APPEND OCRE_IMAGES ${image}) +endforeach() diff --git a/src/ocre/CMakeLists.txt b/src/ocre/CMakeLists.txt index 23933496..d043c54f 100644 --- a/src/ocre/CMakeLists.txt +++ b/src/ocre/CMakeLists.txt @@ -64,3 +64,9 @@ target_include_directories(OcreCore PUBLIC include ) + +include (../../cmake/state_information.cmake) + +if(OCRE_IMAGES) + add_dependencies(OcreCore ${OCRE_IMAGES}) +endif() diff --git a/src/platform/posix/include/ocre/platform/config.h b/src/platform/posix/include/ocre/platform/config.h index f59b2a60..5d2fc681 100644 --- a/src/platform/posix/include/ocre/platform/config.h +++ b/src/platform/posix/include/ocre/platform/config.h @@ -1,7 +1,7 @@ #ifndef OCRE_PLATFORM_POSIX_H #define OCRE_PLATFORM_POSIX_H -#define CONFIG_OCRE_DEFAULT_WORKING_DIRECTORY "./var/lib/ocre" +#define CONFIG_OCRE_DEFAULT_WORKING_DIRECTORY "src/ocre/var/lib/ocre" #define CONFIG_OCRE_WAMR_INTERPRETER 1 #define CONFIG_OCRE_WAMR_AOT 1 diff --git a/src/samples/demo/posix/CMakeLists.txt b/src/samples/demo/posix/CMakeLists.txt index e13656c7..0cf4d426 100644 --- a/src/samples/demo/posix/CMakeLists.txt +++ b/src/samples/demo/posix/CMakeLists.txt @@ -1,6 +1,5 @@ cmake_minimum_required(VERSION 3.20.0) -set(OCRE_DEFAULT_WORKING_DIRECTORY "/var/lib/ocre") project (ocre_sample_demo) @@ -17,8 +16,3 @@ target_link_libraries(ocre_demo PRIVATE -lpthread ) - -add_dependencies(ocre_demo - OcreSampleContainers - OcrePreloadedImages -) diff --git a/src/samples/demo/zephyr/CMakeLists.txt b/src/samples/demo/zephyr/CMakeLists.txt index 2997f0f5..cacf8b37 100644 --- a/src/samples/demo/zephyr/CMakeLists.txt +++ b/src/samples/demo/zephyr/CMakeLists.txt @@ -25,6 +25,5 @@ target_link_libraries(app ) add_dependencies(app - OcrePreloadedImages OcreSampleContainers ) diff --git a/src/samples/mini/posix/CMakeLists.txt b/src/samples/mini/posix/CMakeLists.txt index c8fc45ea..3b8767af 100644 --- a/src/samples/mini/posix/CMakeLists.txt +++ b/src/samples/mini/posix/CMakeLists.txt @@ -1,6 +1,5 @@ cmake_minimum_required(VERSION 3.20.0) -set(OCRE_DEFAULT_WORKING_DIRECTORY "/var/lib/ocre") project (ocre_sample_mini) diff --git a/zephyr/storage_partition.cmake b/zephyr/storage_partition.cmake index 794c7d78..ceb109eb 100644 --- a/zephyr/storage_partition.cmake +++ b/zephyr/storage_partition.cmake @@ -1,28 +1,31 @@ cmake_minimum_required(VERSION 3.20.0) -include(../cmake/state_information.cmake) - -add_custom_command(OUTPUT user_data.littlefs - COMMAND littlefs-python create --block-size ${CONFIG_OCRE_STORAGE_PARTITION_BLOCK_SIZE} --fs-size ${CONFIG_OCRE_STORAGE_PARTITION_SIZE} var/lib user_data.littlefs - DEPENDS ${OCRE_IMAGES} - COMMENT "Generating user_data.littlefs" +add_custom_command(OUTPUT user_data.bin + COMMAND littlefs-python create + --block-size ${CONFIG_OCRE_STORAGE_PARTITION_BLOCK_SIZE} + --fs-size ${CONFIG_OCRE_STORAGE_PARTITION_SIZE} + ocre-core/var/lib user_data.bin + DEPENDS ${OCRE_SDK_PRELOADED_IMAGES} + COMMENT "Generating user_data.bin" VERBATIM ) -add_custom_command(OUTPUT user_data.littlefs.hex - COMMAND bin2hex.py --offset ${CONFIG_OCRE_STORAGE_PARTITION_ADDR} user_data.littlefs user_data.littlefs.hex - DEPENDS user_data.littlefs - COMMENT "Generating user_data.littlefs.hex" +add_custom_command(OUTPUT user_data.hex + COMMAND bin2hex.py + --offset ${CONFIG_OCRE_STORAGE_PARTITION_ADDR} + user_data.bin user_data.hex + DEPENDS user_data.bin + COMMENT "Generating user_data.hex" VERBATIM ) add_custom_target(user_data_partition ALL - DEPENDS user_data.littlefs.hex + DEPENDS user_data.hex COMMENT "Generating user data partition" VERBATIM ) if (CONFIG_OCRE_MERGE_HEX) - set_property(GLOBAL APPEND PROPERTY HEX_FILES_TO_MERGE "${CMAKE_CURRENT_BINARY_DIR}/user_data.littlefs.hex") + set_property(GLOBAL APPEND PROPERTY HEX_FILES_TO_MERGE "${CMAKE_CURRENT_BINARY_DIR}/user_data.hex") set_property(GLOBAL APPEND PROPERTY HEX_FILES_TO_MERGE "zephyr.hex") endif() From 8957fca087bbf02919190bc9514949f27d6815f3 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 10 Dec 2025 18:34:03 +0100 Subject: [PATCH 078/234] fix(context): only parse if arguments are provided Signed-off-by: Marco Casaroli --- src/ocre/container.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ocre/container.c b/src/ocre/container.c index 4adec47c..c7587eae 100644 --- a/src/ocre/container.c +++ b/src/ocre/container.c @@ -138,7 +138,7 @@ struct ocre_container *ocre_container_create(const char *img_path, const char *w * We handle '/' with the 'filesystem' capability. */ - if (arguments->mounts) { + if (arguments && arguments->mounts) { const char **mount = arguments->mounts; while (*mount) { From 9dd45e0d570525284b239d3343bed8697bcea375 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 10 Dec 2025 18:35:09 +0100 Subject: [PATCH 079/234] fix(container): do not remove . or .. These are not real directories. In linux they appear in the listing of directories, so we just ignore them. Signed-off-by: Marco Casaroli --- src/ocre/context.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/ocre/context.c b/src/ocre/context.c index 514e1dae..cbe5627e 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -54,6 +54,11 @@ static int delete_container_workdirs(const char *working_directory) } while ((dir = readdir(d)) != NULL) { + + if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, "..")) { + continue; + } + char *container_workdir_path = malloc(strlen(containers_path) + strlen(dir->d_name) + 2); if (!container_workdir_path) { fprintf(stderr, "Failed to allocate memory for container workdir path\n"); @@ -76,11 +81,11 @@ static int delete_container_workdirs(const char *working_directory) ret = 0; finish: - if (d) { - closedir(d); - } + if (d) { + closedir(d); + } - free(containers_path); + free(containers_path); return ret; } From 1e63f95fc0ef1e485d723bc300655d4ec051318b Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 11 Dec 2025 09:31:21 +0100 Subject: [PATCH 080/234] remove spurious readline example Signed-off-by: Marco Casaroli --- src/samples/readline/posix/CMakeLists.txt | 38 --------------- src/samples/readline/posix/ocre.c | 56 ----------------------- 2 files changed, 94 deletions(-) delete mode 100644 src/samples/readline/posix/CMakeLists.txt delete mode 100644 src/samples/readline/posix/ocre.c diff --git a/src/samples/readline/posix/CMakeLists.txt b/src/samples/readline/posix/CMakeLists.txt deleted file mode 100644 index 076ae100..00000000 --- a/src/samples/readline/posix/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -cmake_minimum_required(VERSION 3.20.0) - -project (ocre_sample_supervisor) - -add_executable(ocred - ocred.c -) - -target_link_libraries(ocred - PUBLIC - OcreCore -) - -target_link_libraries(ocred - PRIVATE - -lpthread -) - -add_executable(ocre - ocre.c -) - -target_link_libraries(ocre - PUBLIC - OcreCore # just link for now, to validate the build - OcreShell -) - -target_link_libraries(OcreShell - PUBLIC - OcreCore -) - - -target_link_libraries(ocre - PRIVATE - -lpthread -) diff --git a/src/samples/readline/posix/ocre.c b/src/samples/readline/posix/ocre.c deleted file mode 100644 index c40bf457..00000000 --- a/src/samples/readline/posix/ocre.c +++ /dev/null @@ -1,56 +0,0 @@ -#include -#include -#include - -#include - -#include // remove - -// keep a reference to the single instance of the runtime -struct ocre_context *ocre_global_context = NULL; - -int main(int argc, char *argv[]) -{ - // Initialize OCRE - if (ocre_initialize() != 0) { - return -1; - } - - fprintf(stderr, "Initialized Ocre\n"); - - // Create a context - ocre_global_context = ocre_create_context("var/lib/ocre"); - if (!ocre_global_context) { - fprintf(stderr, "Failed to create Ocre context\n"); - ocre_deinitialize(); - return -1; - } - - fprintf(stderr, "Created Ocre context: %p\n", ocre_global_context); - - struct ocre_container *hello = - ocre_context_create_container(ocre_global_context, "hello-world.wasm", "wamr", "marco", true, NULL); - - if (!hello) { - fprintf(stderr, "Failed to create container\n"); - return 1; - } - - struct ocre_container *subscriber = - ocre_context_create_container(ocre_global_context, "subscriber.wasm", "wamr", NULL, true, NULL); - - if (!subscriber) { - fprintf(stderr, "Failed to create container\n"); - return 1; - } - - struct ocre_container *publisher = - ocre_context_create_container(ocre_global_context, "publisher.wasm", "wamr", NULL, true, NULL); - - if (!publisher) { - fprintf(stderr, "Failed to create container\n"); - return 1; - } - - return ocre_shell(ocre_global_context, argc, argv); -} From 5847dade8097bf262d7e0e981d951fe375f94248 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 11 Dec 2025 09:47:54 +0100 Subject: [PATCH 081/234] build(wamr): enable WASI-Threads and disable libpthread We switch from WAMR libpthread to WASI-Threads, which require changes in ocre-sdk. Signed-off-by: Marco Casaroli --- cmake/wamr.cmake | 3 ++- zephyr/wamr.cmake | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/cmake/wamr.cmake b/cmake/wamr.cmake index 2f3d99e1..4fa77dca 100644 --- a/cmake/wamr.cmake +++ b/cmake/wamr.cmake @@ -4,7 +4,8 @@ set (WAMR_BUILD_AOT 0) set (WAMR_BUILD_JIT 0) set (WAMR_BUILD_LIBC_BUILTIN 0) set (WAMR_BUILD_LIBC_WASI 1) -set (WAMR_BUILD_LIB_PTHREAD 1) +set (WAMR_BUILD_LIB_PTHREAD 0) +set (WAMR_BUILD_LIB_WASI_THREADS 1) set (WAMR_BUILD_REF_TYPES 1) set (WASM_ENABLE_LOG 1) set (WAMR_BUILD_SHARED_HEAP 1) diff --git a/zephyr/wamr.cmake b/zephyr/wamr.cmake index f2c7791a..d1afea62 100644 --- a/zephyr/wamr.cmake +++ b/zephyr/wamr.cmake @@ -23,9 +23,10 @@ set(WAMR_BUILD_INTERP 1) set(WAMR_BUILD_FAST_INTERP 0) set(WAMR_BUILD_AOT 0) set(WAMR_BUILD_JIT 0) -set(WAMR_BUILD_LIBC_BUILTIN 1) +set(WAMR_BUILD_LIBC_BUILTIN 0) set(WAMR_BUILD_LIBC_WASI 1) -set(WAMR_BUILD_LIB_PTHREAD 1) +set(WAMR_BUILD_LIB_WASI_THREADS 1) +set(WAMR_BUILD_LIB_PTHREAD 0) set(WAMR_BUILD_REF_TYPES 1) set(WAMR_BUILD_SHARED_HEAP 1) set(WASM_ENABLE_LOG 1) From da369fff4beb6b7c8f6604981a675898e1a9e91a Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 11 Dec 2025 09:48:55 +0100 Subject: [PATCH 082/234] feat(wamr): enable AOT Signed-off-by: Marco Casaroli --- cmake/wamr.cmake | 2 +- zephyr/wamr.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/wamr.cmake b/cmake/wamr.cmake index 4fa77dca..2c55be2e 100644 --- a/cmake/wamr.cmake +++ b/cmake/wamr.cmake @@ -1,6 +1,6 @@ set (WAMR_BUILD_INTERP 1) set (WAMR_BUILD_FAST_INTERP 0) -set (WAMR_BUILD_AOT 0) +set (WAMR_BUILD_AOT 1) set (WAMR_BUILD_JIT 0) set (WAMR_BUILD_LIBC_BUILTIN 0) set (WAMR_BUILD_LIBC_WASI 1) diff --git a/zephyr/wamr.cmake b/zephyr/wamr.cmake index d1afea62..9224f724 100644 --- a/zephyr/wamr.cmake +++ b/zephyr/wamr.cmake @@ -21,7 +21,7 @@ set(WAMR_BUILD_PLATFORM "zephyr") set(WAMR_BUILD_TARGET ${TARGET_ISA}) set(WAMR_BUILD_INTERP 1) set(WAMR_BUILD_FAST_INTERP 0) -set(WAMR_BUILD_AOT 0) +set(WAMR_BUILD_AOT 1) set(WAMR_BUILD_JIT 0) set(WAMR_BUILD_LIBC_BUILTIN 0) set(WAMR_BUILD_LIBC_WASI 1) From ec68f3ba4eb41794a0baa7778f97ebc4d82dac24 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 11 Dec 2025 09:49:33 +0100 Subject: [PATCH 083/234] feat(wamr): disable global heap pool We do not use it anymore. We use the allocato functions instead. Signed-off-by: Marco Casaroli --- cmake/wamr.cmake | 12 ++++++------ zephyr/wamr.cmake | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cmake/wamr.cmake b/cmake/wamr.cmake index 2c55be2e..eef3adb9 100644 --- a/cmake/wamr.cmake +++ b/cmake/wamr.cmake @@ -14,12 +14,12 @@ if (NOT DEFINED WAMR_BUILD_PLATFORM) set (WAMR_BUILD_PLATFORM "linux") endif() -if (NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_POOL) - set (WAMR_BUILD_GLOBAL_HEAP_POOL 1) -endif () -if (NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_SIZE) - set (WAMR_BUILD_GLOBAL_HEAP_SIZE 32767) -endif () +# if (NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_POOL) +# set (WAMR_BUILD_GLOBAL_HEAP_POOL 1) +# endif () +# if (NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_SIZE) +# set (WAMR_BUILD_GLOBAL_HEAP_SIZE 32767) +# endif () # Set WAMR_BUILD_TARGET, currently values supported: # "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", diff --git a/zephyr/wamr.cmake b/zephyr/wamr.cmake index 9224f724..4bb1aafb 100644 --- a/zephyr/wamr.cmake +++ b/zephyr/wamr.cmake @@ -34,12 +34,12 @@ set(WASM_ENABLE_LOG 1) # DEBUG #set(WAMR_BUILD_DEBUG_INTERP 1) -if(NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_POOL) - set(WAMR_BUILD_GLOBAL_HEAP_POOL 1) -endif() -if(NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_SIZE) - set(WAMR_BUILD_GLOBAL_HEAP_SIZE 32767) -endif() +# if(NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_POOL) +# set(WAMR_BUILD_GLOBAL_HEAP_POOL 1) +# endif() +# if(NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_SIZE) +# set(WAMR_BUILD_GLOBAL_HEAP_SIZE 32767) +# endif() enable_language (ASM) From 0c424944c9aa2928917d69e1c2aa4264df423d5a Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 11 Dec 2025 16:55:25 +0100 Subject: [PATCH 084/234] fix(samples/supervisor): harmonize configurations Some configurations are to be in prj.conf not on the board specific config. We also set the dependencies for networking inside the Kconfig. Signed-off-by: Marco Casaroli --- .../zephyr/boards/pico_plus2_rp2350b_m33_w.conf | 4 +--- .../boards/pico_plus2_rp2350b_m33_w_mcuboot.conf | 6 ++---- src/samples/supervisor/zephyr/prj.conf | 11 +++-------- zephyr/Kconfig | 8 +++++++- 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.conf b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.conf index b8692911..880b21ea 100644 --- a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.conf +++ b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.conf @@ -1,6 +1,4 @@ CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_SHARED_MULTI_HEAP=y - -# for led -CONFIG_NETWORKING=y CONFIG_WIFI=y +CONFIG_NET_L2_WIFI_SHELL=y diff --git a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w_mcuboot.conf b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w_mcuboot.conf index 9799284a..880b21ea 100644 --- a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w_mcuboot.conf +++ b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w_mcuboot.conf @@ -1,6 +1,4 @@ CONFIG_TEST_RANDOM_GENERATOR=y - -# for led -CONFIG_NETWORKING=y +CONFIG_SHARED_MULTI_HEAP=y CONFIG_WIFI=y -CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_NET_L2_WIFI_SHELL=y diff --git a/src/samples/supervisor/zephyr/prj.conf b/src/samples/supervisor/zephyr/prj.conf index 18b243f8..4efa9490 100644 --- a/src/samples/supervisor/zephyr/prj.conf +++ b/src/samples/supervisor/zephyr/prj.conf @@ -2,17 +2,11 @@ CONFIG_SHELL=y CONFIG_BOOT_BANNER=y CONFIG_SHELL_PROMPT_UART="ocre:~$ " CONFIG_NET_SHELL=y -CONFIG_NET_L2_WIFI_SHELL=n CONFIG_FILE_SYSTEM_SHELL=y CONFIG_LOG=y # Networking options -CONFIG_NET_IPV4=y -CONFIG_NET_IPV6=y -CONFIG_NET_UDP=y -CONFIG_NET_SOCKETS=y - CONFIG_NET_TX_STACK_SIZE=2048 CONFIG_NET_BUF_TX_COUNT=16 CONFIG_NET_RX_STACK_SIZE=4096 @@ -20,8 +14,8 @@ CONFIG_NET_BUF_RX_COUNT=32 CONFIG_NET_MGMT_EVENT_STACK_SIZE=2048 # file descriptors -CONFIG_ZVFS_POLL_MAX=5 -CONFIG_ZVFS_OPEN_MAX=8 +CONFIG_ZVFS_POLL_MAX=16 +CONFIG_ZVFS_OPEN_MAX=16 CONFIG_NET_DHCPV4=y @@ -36,6 +30,7 @@ CONFIG_POSIX_THREAD_THREADS_MAX=32 # Ocre configuration CONFIG_OCRE=y +CONFIG_OCRE_NETWORKING=y CONFIG_OCRE_SHELL=y CONFIG_OCRE_TIMER=y CONFIG_OCRE_CONTAINER_MESSAGING=y diff --git a/zephyr/Kconfig b/zephyr/Kconfig index c8beb5ec..90e62e16 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -92,6 +92,11 @@ comment "Container features" config OCRE_NETWORKING bool "Enable container networking support" default n + select NET_IPV4 + select NET_IPV6 + select NET_UDP + select NET_TCP + select NET_SOCKETS help Enable networking support for containers. @@ -188,7 +193,8 @@ comment "Control Interface" config OCRE_SHELL bool "Enable OCRE Shell" - # depends on SHELL + select SHELL + select SHELL_GETOPT default n help Enable the OCRE Shell for dynamic configuration management. From 28b5cdbaacf5885cba8d3f8a5aa9d2d3f2e864ac Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 11 Dec 2025 16:57:01 +0100 Subject: [PATCH 085/234] fix(state_information): remove volumes This will hopefully be added in the future. Signed-off-by: Marco Casaroli --- cmake/state_information.cmake | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmake/state_information.cmake b/cmake/state_information.cmake index 52aa0d3c..0a18f5f0 100644 --- a/cmake/state_information.cmake +++ b/cmake/state_information.cmake @@ -1,7 +1,6 @@ cmake_minimum_required(VERSION 3.20.0) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/var/lib/ocre/images) -file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/var/lib/ocre/volumes) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/var/lib/ocre/containers) if(OCRE_SDK_PRELOADED_IMAGES) @@ -13,7 +12,7 @@ if(OCRE_SDK_PRELOADED_IMAGES) BUILD_ALWAYS TRUE INSTALL_COMMAND "" SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../ocre-sdk" - CMAKE_ARGS "-DWAMR_ROOT_DIR=${CMAKE_CURRENT_LIST_DIR}/../wasm-micro-runtime" + CMAKE_ARGS "-DWAMR_ROOT_DIR=${CMAKE_CURRENT_LIST_DIR}/../wasm-micro-runtime" "-DCMAKE_VERBOSE_MAKEFILE=ON" ) endif() From 883a1b9655aa668c79c56035d2542567d246d680 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 11 Dec 2025 17:04:07 +0100 Subject: [PATCH 086/234] fix(.gitignore): typo Signed-off-by: Marco Casaroli --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index e5b4b204..377de330 100644 --- a/.gitignore +++ b/.gitignore @@ -62,4 +62,4 @@ src/ocre/commit_id.h !/.gitmodules !/.github !.devcontainer -!.ckang-format +!.clang-format From 4cb406f8930e76b78cad8760ab998c30cc321d53 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 11 Dec 2025 19:09:35 +0100 Subject: [PATCH 087/234] fix(log): fix loggin for POSIX and harmonize with zephyr The zephyr log interface seems good enough. Signed-off-by: Marco Casaroli --- src/ocre/container.c | 2 +- src/ocre/context.c | 2 +- src/ocre/ocre.c | 2 +- src/platform/posix/CMakeLists.txt | 1 + src/platform/posix/file_alloc_fread.c | 2 +- src/platform/posix/file_alloc_read.c | 2 +- src/platform/posix/file_mmap.c | 2 +- .../posix/include/ocre/platform/config.h | 4 +-- .../posix/include/ocre/platform/log.h | 32 ++++++++++++++++--- src/platform/posix/log.c | 3 ++ src/runtime/wamr/ocre_api/ocre_common.c | 2 +- .../wamr/ocre_api/ocre_gpio/ocre_gpio.c | 2 +- .../ocre_api/ocre_messaging/ocre_messaging.c | 2 +- .../wamr/ocre_api/ocre_sensors/ocre_sensors.c | 2 +- .../wamr/ocre_api/ocre_timers/ocre_timer.c | 2 +- src/runtime/wamr/wamr.c | 2 +- src/samples/bash_runtime/posix/bash/bash.c | 2 +- 17 files changed, 47 insertions(+), 19 deletions(-) create mode 100644 src/platform/posix/log.c diff --git a/src/ocre/container.c b/src/ocre/container.c index c7587eae..fcc57a7e 100644 --- a/src/ocre/container.c +++ b/src/ocre/container.c @@ -13,7 +13,7 @@ #include "container.h" #include "util/string_array.h" -LOG_MODULE_REGISTER(container); +LOG_MODULE_REGISTER(container, CONFIG_OCRE_LOG_LEVEL); struct ocre_container { char *id; diff --git a/src/ocre/context.c b/src/ocre/context.c index cbe5627e..ac2bc97e 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -19,7 +19,7 @@ #define RANDOM_ID_LEN 8 -LOG_MODULE_REGISTER(context); +LOG_MODULE_REGISTER(context, CONFIG_OCRE_LOG_LEVEL); struct ocre_context { pthread_mutex_t mutex; diff --git a/src/ocre/ocre.c b/src/ocre/ocre.c index b4854afd..ed5f6149 100644 --- a/src/ocre/ocre.c +++ b/src/ocre/ocre.c @@ -15,7 +15,7 @@ #include "commit_id.h" #include "version.h" -LOG_MODULE_REGISTER(ocre); +LOG_MODULE_REGISTER(ocre, CONFIG_OCRE_LOG_LEVEL); /* Constant build information */ diff --git a/src/platform/posix/CMakeLists.txt b/src/platform/posix/CMakeLists.txt index 50bede67..012e220c 100644 --- a/src/platform/posix/CMakeLists.txt +++ b/src/platform/posix/CMakeLists.txt @@ -3,6 +3,7 @@ add_library(OcrePlatform) target_sources(OcrePlatform PRIVATE memory.c + log.c file_mmap.c # file_alloc_read.c ) diff --git a/src/platform/posix/file_alloc_fread.c b/src/platform/posix/file_alloc_fread.c index 30c4e631..0c73c823 100644 --- a/src/platform/posix/file_alloc_fread.c +++ b/src/platform/posix/file_alloc_fread.c @@ -10,7 +10,7 @@ #include #include -LOG_MODULE_REGISTER(file_alloc_fread); +LOG_MODULE_REGISTER(file_alloc_fread, CONFIG_OCRE_LOG_LEVEL); void *ocre_load_file(const char *path, size_t *size) { diff --git a/src/platform/posix/file_alloc_read.c b/src/platform/posix/file_alloc_read.c index df07e44a..956d3d51 100644 --- a/src/platform/posix/file_alloc_read.c +++ b/src/platform/posix/file_alloc_read.c @@ -11,7 +11,7 @@ #include #include -LOG_MODULE_REGISTER(file_alloc_read); +LOG_MODULE_REGISTER(file_alloc_read, CONFIG_OCRE_LOG_LEVEL); void *ocre_load_file(const char *path, size_t *size) { diff --git a/src/platform/posix/file_mmap.c b/src/platform/posix/file_mmap.c index a9eb4b64..ea1bad8d 100644 --- a/src/platform/posix/file_mmap.c +++ b/src/platform/posix/file_mmap.c @@ -10,7 +10,7 @@ #include #include -LOG_MODULE_REGISTER(file_mmap); +LOG_MODULE_REGISTER(file_mmap, CONFIG_OCRE_LOG_LEVEL); void *ocre_load_file(const char *path, size_t *size) { diff --git a/src/platform/posix/include/ocre/platform/config.h b/src/platform/posix/include/ocre/platform/config.h index 5d2fc681..481a4b78 100644 --- a/src/platform/posix/include/ocre/platform/config.h +++ b/src/platform/posix/include/ocre/platform/config.h @@ -10,8 +10,8 @@ #define CONFIG_OCRE_CONTAINER_DEFAULT_STACK_SIZE 2048 #define CONFIG_OCRE_TIMER 1 #define CONFIG_OCRE_MAX_TIMERS 5 -#define CONFIG_OCRE_LOG_LEVEL_DEFAULT 1 -#define CONFIG_OCRE_LOG_LEVEL 3 +#define CONFIG_OCRE_LOG_LEVEL_DEFAULT 3 +#define CONFIG_OCRE_LOG_LEVEL 4 #define CONFIG_OCRE_NETWORKING 1 #define CONFIG_OCRE_FILESYSTEM 1 #define CONFIG_OCRE_CONTAINER_MESSAGING 1 diff --git a/src/platform/posix/include/ocre/platform/log.h b/src/platform/posix/include/ocre/platform/log.h index 7b0d03f2..69197498 100644 --- a/src/platform/posix/include/ocre/platform/log.h +++ b/src/platform/posix/include/ocre/platform/log.h @@ -1,8 +1,32 @@ #include +#include "config.h" + #define LOG_MODULE_REGISTER(module, ...) static const char *const __ocre_log_module = #module +#define LOG_MODULE_DECLARE(module, ...) static const char *const __ocre_log_module = #module + +extern int __ocre_log_level; + +#if CONFIG_OCRE_LOG_LEVEL >= 1 +#define LOG_ERR(fmt, ...) do { if (__ocre_log_level >= 1) fprintf(stderr, " %s: " fmt "\n", __ocre_log_module, ##__VA_ARGS__); } while (0) +#else +#define LOG_ERR(fmt, ...) do {} while (0) +#endif + +#if CONFIG_OCRE_LOG_LEVEL >= 2 +#define LOG_WRN(fmt, ...) do { if (__ocre_log_level >= 2) fprintf(stderr, " %s: " fmt "\n", __ocre_log_module, ##__VA_ARGS__); } while (0) +#else +#define LOG_WRN(fmt, ...) do {} while (0) +#endif + +#if CONFIG_OCRE_LOG_LEVEL >= 3 +#define LOG_INF(fmt, ...) do { if (__ocre_log_level >= 3) fprintf(stderr, " %s: " fmt "\n", __ocre_log_module, ##__VA_ARGS__); } while (0) +#else +#define LOG_INF(fmt, ...) do {} while (0) +#endif -#define LOG_ERR(fmt, ...) fprintf(stderr, " %s: " fmt "\n", __ocre_log_module, ##__VA_ARGS__); -#define LOG_WRN(fmt, ...) fprintf(stderr, " %s: " fmt "\n", __ocre_log_module, ##__VA_ARGS__); -#define LOG_INF(fmt, ...) fprintf(stderr, " %s: " fmt "\n", __ocre_log_module, ##__VA_ARGS__); -#define LOG_DBG(fmt, ...) fprintf(stderr, " %s: " fmt "\n", __ocre_log_module, ##__VA_ARGS__); +#if CONFIG_OCRE_LOG_LEVEL >= 4 +#define LOG_DBG(fmt, ...) do { if (__ocre_log_level >= 4) fprintf(stderr, " %s: " fmt "\n", __ocre_log_module, ##__VA_ARGS__); } while (0) +#else +#define LOG_DBG(fmt, ...) do {} while (0) +#endif diff --git a/src/platform/posix/log.c b/src/platform/posix/log.c new file mode 100644 index 00000000..ef0a97e5 --- /dev/null +++ b/src/platform/posix/log.c @@ -0,0 +1,3 @@ +#include + +int __ocre_log_level = CONFIG_OCRE_LOG_LEVEL_DEFAULT; diff --git a/src/runtime/wamr/ocre_api/ocre_common.c b/src/runtime/wamr/ocre_api/ocre_common.c index a734b5fb..85263a34 100644 --- a/src/runtime/wamr/ocre_api/ocre_common.c +++ b/src/runtime/wamr/ocre_api/ocre_common.c @@ -17,7 +17,7 @@ #include "core/core_external.h" -LOG_MODULE_REGISTER(ocre_common, 4); +LOG_MODULE_REGISTER(ocre_common, CONFIG_OCRE_LOG_LEVEL); #ifdef CONFIG_OCRE_GPIO #include "ocre_gpio/ocre_gpio.h" diff --git a/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.c b/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.c index 4e3af14e..84bd8c01 100644 --- a/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.c +++ b/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.c @@ -14,7 +14,7 @@ #include #include -LOG_MODULE_REGISTER(ocre_gpio, 4); +LOG_MODULE_REGISTER(ocre_gpio, CONFIG_OCRE_LOG_LEVEL); typedef struct { uint32_t in_use: 1; diff --git a/src/runtime/wamr/ocre_api/ocre_messaging/ocre_messaging.c b/src/runtime/wamr/ocre_api/ocre_messaging/ocre_messaging.c index f726a659..61f3c096 100644 --- a/src/runtime/wamr/ocre_api/ocre_messaging/ocre_messaging.c +++ b/src/runtime/wamr/ocre_api/ocre_messaging/ocre_messaging.c @@ -13,7 +13,7 @@ #include "ocre_messaging.h" #include "../ocre_common.h" -LOG_MODULE_REGISTER(ocre_messaging, 4); +LOG_MODULE_REGISTER(ocre_messaging, CONFIG_OCRE_LOG_LEVEL); #ifndef CONFIG_OCRE_MESSAGING_MAX_SUBSCRIPTIONS #define CONFIG_OCRE_MESSAGING_MAX_SUBSCRIPTIONS 10 diff --git a/src/runtime/wamr/ocre_api/ocre_sensors/ocre_sensors.c b/src/runtime/wamr/ocre_api/ocre_sensors/ocre_sensors.c index 03358e9b..f304ed86 100644 --- a/src/runtime/wamr/ocre_api/ocre_sensors/ocre_sensors.c +++ b/src/runtime/wamr/ocre_api/ocre_sensors/ocre_sensors.c @@ -9,7 +9,7 @@ #include #include #include -LOG_MODULE_REGISTER(ocre_sensors, 4); +LOG_MODULE_REGISTER(ocre_sensors, CONFIG_OCRE_LOG_LEVEL); #include "ocre_sensors.h" diff --git a/src/runtime/wamr/ocre_api/ocre_timers/ocre_timer.c b/src/runtime/wamr/ocre_api/ocre_timers/ocre_timer.c index 414f8079..35e68ff7 100644 --- a/src/runtime/wamr/ocre_api/ocre_timers/ocre_timer.c +++ b/src/runtime/wamr/ocre_api/ocre_timers/ocre_timer.c @@ -20,7 +20,7 @@ #include "../ocre_common.h" #include "ocre_timer.h" -LOG_MODULE_REGISTER(ocre_timer, 4); +LOG_MODULE_REGISTER(ocre_timer, CONFIG_OCRE_LOG_LEVEL); /* Unified timer structure using core_timer API */ typedef struct { diff --git a/src/runtime/wamr/wamr.c b/src/runtime/wamr/wamr.c index 9a71c97b..8f8a69d1 100644 --- a/src/runtime/wamr/wamr.c +++ b/src/runtime/wamr/wamr.c @@ -20,7 +20,7 @@ #include "ocre_api/ocre_common.h" #include "ocre_api/ocre_timers/ocre_timer.h" -LOG_MODULE_REGISTER(wamr_runtime, 3); +LOG_MODULE_REGISTER(wamr_runtime, CONFIG_OCRE_LOG_LEVEL); static wasm_shared_heap_t _shared_heap = NULL; diff --git a/src/samples/bash_runtime/posix/bash/bash.c b/src/samples/bash_runtime/posix/bash/bash.c index 77ce7965..58f6acef 100644 --- a/src/samples/bash_runtime/posix/bash/bash.c +++ b/src/samples/bash_runtime/posix/bash/bash.c @@ -14,7 +14,7 @@ #include -LOG_MODULE_REGISTER(bash_runtime); +LOG_MODULE_REGISTER(bash_runtime, CONFIG_OCRE_LOG_LEVEL); struct bash_context { pid_t pid; From 326c4ee0670cf993dd97eebbffbe4d2829f80682 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 11 Dec 2025 19:10:37 +0100 Subject: [PATCH 088/234] chore: remove libwebsockets Signed-off-by: Marco Casaroli --- .gitmodules | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index dcc009fb..45cc66c8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,9 +2,6 @@ path = wasm-micro-runtime url = https://github.com/project-ocre/wasm-micro-runtime.git branch = staging -[submodule "libwebsockets"] - path = libwebsockets - url = https://libwebsockets.org/repo/libwebsockets [submodule "ocre-sdk"] path = ocre-sdk url = git@github.com:project-ocre/ocre-sdk.git From 88b82beaef6eb4debb33b3c9931b059f7f2f77ff Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 11 Dec 2025 19:20:57 +0100 Subject: [PATCH 089/234] chore: remove unused files Signed-off-by: Marco Casaroli --- Dockerfile | 79 -- TODO.txt | 40 - src/ocre/include/uthash/utarray.h | 258 ------ src/ocre/include/uthash/uthash.h | 1137 ------------------------ src/ocre/include/uthash/utringbuffer.h | 108 --- src/ocre/include/uthash/utstack.h | 88 -- src/ocre/include/uthash/utstring.h | 407 --------- 7 files changed, 2117 deletions(-) delete mode 100644 Dockerfile delete mode 100644 TODO.txt delete mode 100644 src/ocre/include/uthash/utarray.h delete mode 100644 src/ocre/include/uthash/uthash.h delete mode 100644 src/ocre/include/uthash/utringbuffer.h delete mode 100644 src/ocre/include/uthash/utstack.h delete mode 100644 src/ocre/include/uthash/utstring.h diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 0a73d2b8..00000000 --- a/Dockerfile +++ /dev/null @@ -1,79 +0,0 @@ -FROM ubuntu:22.04 - -# for apt to be noninteractive -ENV DEBIAN_FRONTEND=noninteractive -ENV DEBCONF_NONINTERACTIVE_SEEN=true - -RUN truncate -s0 /tmp/preseed.cfg; \ - echo "tzdata tzdata/Areas select Europe" >> /tmp/preseed.cfg; \ - echo "tzdata tzdata/Zones/Europe select Madrid" >> /tmp/preseed.cfg; \ - debconf-set-selections /tmp/preseed.cfg && \ - rm -f /etc/timezone /etc/localtime - -RUN apt-get -q update && apt-get install --no-install-recommends -y\ - build-essential\ - ccache\ - cmake\ - device-tree-compiler\ - dfu-util\ - file\ - gcc\ - g++\ - git\ - gperf\ - libmagic1\ - locales\ - make\ - ninja-build\ - openssh-server\ - python3\ - python3-dev\ - python3-venv\ - sudo\ - supervisor\ - tzdata\ - wget\ - xz-utils - -RUN /usr/sbin/locale-gen en_US.UTF-8 -ENV LANG=en_US.UTF-8 - -RUN mkdir -p /var/run/sshd /var/log/supervisor - -#COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf - -RUN cat << EOF > /etc/supervisor/conf.d/supervisord.conf -[supervisord] -nodaemon=true -user=root - -[program:sshd] -command=/usr/sbin/sshd -D -autostart=true -autorestart=true -EOF - -EXPOSE 22 -CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"] - -# create users -RUN echo "[color]\n\tui = false\n[user]\n\tname = Marco\n\temail = marco.casaroli@gmail.com" > /etc/skel/.gitconfig - -ARG USER_NAME=marco - -# ===== create user/setup environment ===== -# this is for ubuntu user (uid=1000, gid=1000) -RUN useradd --create-home --shell /bin/bash --groups sudo ${USER_NAME} -RUN echo "${USER_NAME} ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/${USER_NAME} - -RUN \ - mkdir -p /home/${USER_NAME}/.ssh/ &&\ - echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHOQDCuzFBPW2VeYBGhcmJgoecMM99Uea/C4gExUqZPn marco@Marcos-Silver-MacBook-Pro.local" > /home/${USER_NAME}/.ssh/authorized_keys &&\ - chown -R ${USER_NAME}:${USER_NAME} /home/${USER_NAME}/.ssh - -# use bash as shell -SHELL ["/bin/bash", "-c"] - -# working directory -#USER ${USER_NAME} -#WORKDIR /home/${USER_NAME} diff --git a/TODO.txt b/TODO.txt deleted file mode 100644 index 0d7c5e2d..00000000 --- a/TODO.txt +++ /dev/null @@ -1,40 +0,0 @@ -# TODO MVP - -- version DONE -- sample container DONE -- detached create DONE -- envp argv handle copy in ocre not runtime DONE -- capabilities DONE -- shared heap DONE -- supervisor shell integration in zephyr DONE -- zephyr littlefs integration user partition DONE -- ocre api - - timer DONE - - messaging DONE - - gpio - - sensor -- timer cleanup -- dir mounts -- http client -- shell container stop -- shell image pull -- shell container inspect -- shell container wait -- documentation -- fix hack for commit id and build info -- CONFIG_THREAD_RUNTIME_STATS # needed by the latest version of WARM for time APIs -- IPC / remote context -- log level posix -- log integration review - -- wamr stop -- pause/resume -- SHELL pause/unpause -- tests -- https client -- io redirection -- ocre attach -- ocre volume -- wamr zephyr build -- SHELL stop -- SHELL status diff --git a/src/ocre/include/uthash/utarray.h b/src/ocre/include/uthash/utarray.h deleted file mode 100644 index 16760f9d..00000000 --- a/src/ocre/include/uthash/utarray.h +++ /dev/null @@ -1,258 +0,0 @@ -/* -Copyright (c) 2008-2025, Troy D. Hanson https://troydhanson.github.io/uthash/ -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/* a dynamic array implementation using macros - */ -#ifndef UTARRAY_H -#define UTARRAY_H - -#define UTARRAY_VERSION 2.3.0 - -#include /* size_t */ -#include /* memset, etc */ -#include /* exit */ - -#ifdef __GNUC__ -#define UTARRAY_UNUSED __attribute__((__unused__)) -#else -#define UTARRAY_UNUSED -#endif - -#ifndef utarray_oom -#define utarray_oom() exit(-1) -#endif - -typedef void (ctor_f)(void *dst, const void *src); -typedef void (dtor_f)(void *elt); -typedef void (init_f)(void *elt); -typedef struct { - size_t sz; - init_f *init; - ctor_f *copy; - dtor_f *dtor; -} UT_icd; - -typedef struct { - unsigned i,n;/* i: index of next available slot, n: num slots */ - UT_icd icd; /* initializer, copy and destructor functions */ - char *d; /* n slots of size icd->sz*/ -} UT_array; - -#define utarray_init(a,_icd) do { \ - memset(a,0,sizeof(UT_array)); \ - (a)->icd = *(_icd); \ -} while(0) - -#define utarray_done(a) do { \ - if ((a)->n) { \ - if ((a)->icd.dtor) { \ - unsigned _ut_i; \ - for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \ - (a)->icd.dtor(utarray_eltptr(a,_ut_i)); \ - } \ - } \ - free((a)->d); \ - } \ - (a)->n=0; \ -} while(0) - -#define utarray_new(a,_icd) do { \ - (a) = (UT_array*)malloc(sizeof(UT_array)); \ - if ((a) == NULL) { \ - utarray_oom(); \ - } \ - utarray_init(a,_icd); \ -} while(0) - -#define utarray_free(a) do { \ - utarray_done(a); \ - free(a); \ -} while(0) - -#define utarray_reserve(a,by) do { \ - if (((a)->i+(by)) > (a)->n) { \ - char *utarray_tmp; \ - while (((a)->i+(by)) > (a)->n) { (a)->n = ((a)->n ? (2*(a)->n) : 8); } \ - utarray_tmp=(char*)realloc((a)->d, (a)->n*(a)->icd.sz); \ - if (utarray_tmp == NULL) { \ - utarray_oom(); \ - } \ - (a)->d=utarray_tmp; \ - } \ -} while(0) - -#define utarray_push_back(a,p) do { \ - utarray_reserve(a,1); \ - if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,(a)->i++), p); } \ - else { memcpy(_utarray_eltptr(a,(a)->i++), p, (a)->icd.sz); }; \ -} while(0) - -#define utarray_pop_back(a) do { \ - if ((a)->icd.dtor) { (a)->icd.dtor( _utarray_eltptr(a,--((a)->i))); } \ - else { (a)->i--; } \ -} while(0) - -#define utarray_extend_back(a) do { \ - utarray_reserve(a,1); \ - if ((a)->icd.init) { (a)->icd.init(_utarray_eltptr(a,(a)->i)); } \ - else { memset(_utarray_eltptr(a,(a)->i),0,(a)->icd.sz); } \ - (a)->i++; \ -} while(0) - -#define utarray_len(a) ((a)->i) - -#define utarray_eltptr(a,j) (((j) < (a)->i) ? _utarray_eltptr(a,j) : NULL) -#define _utarray_eltptr(a,j) ((void*)((a)->d + ((a)->icd.sz * (j)))) - -#define utarray_insert(a,p,j) do { \ - if ((j) > (a)->i) utarray_resize(a,j); \ - utarray_reserve(a,1); \ - if ((j) < (a)->i) { \ - memmove( _utarray_eltptr(a,(j)+1), _utarray_eltptr(a,j), \ - ((a)->i - (j))*((a)->icd.sz)); \ - } \ - if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,j), p); } \ - else { memcpy(_utarray_eltptr(a,j), p, (a)->icd.sz); }; \ - (a)->i++; \ -} while(0) - -#define utarray_replace(a,p,j) do { \ - if ((a)->icd.dtor) { (a)->icd.dtor(_utarray_eltptr(a,j)); } \ - if ((a)->icd.copy) { (a)->icd.copy(_utarray_eltptr(a,j), p); } \ - else { memcpy(_utarray_eltptr(a,j), p, (a)->icd.sz); } \ -} while(0) - -#define utarray_inserta(a,w,j) do { \ - if (utarray_len(w) == 0) break; \ - if ((j) > (a)->i) utarray_resize(a,j); \ - utarray_reserve(a,utarray_len(w)); \ - if ((j) < (a)->i) { \ - memmove(_utarray_eltptr(a,(j)+utarray_len(w)), \ - _utarray_eltptr(a,j), \ - ((a)->i - (j))*((a)->icd.sz)); \ - } \ - if ((a)->icd.copy) { \ - unsigned _ut_i; \ - for(_ut_i=0;_ut_i<(w)->i;_ut_i++) { \ - (a)->icd.copy(_utarray_eltptr(a, (j) + _ut_i), _utarray_eltptr(w, _ut_i)); \ - } \ - } else { \ - memcpy(_utarray_eltptr(a,j), _utarray_eltptr(w,0), \ - utarray_len(w)*((a)->icd.sz)); \ - } \ - (a)->i += utarray_len(w); \ -} while(0) - -#define utarray_resize(dst,num) do { \ - unsigned _ut_i; \ - if ((dst)->i > (unsigned)(num)) { \ - if ((dst)->icd.dtor) { \ - for (_ut_i = (num); _ut_i < (dst)->i; ++_ut_i) { \ - (dst)->icd.dtor(_utarray_eltptr(dst, _ut_i)); \ - } \ - } \ - } else if ((dst)->i < (unsigned)(num)) { \ - utarray_reserve(dst, (num) - (dst)->i); \ - if ((dst)->icd.init) { \ - for (_ut_i = (dst)->i; _ut_i < (unsigned)(num); ++_ut_i) { \ - (dst)->icd.init(_utarray_eltptr(dst, _ut_i)); \ - } \ - } else { \ - memset(_utarray_eltptr(dst, (dst)->i), 0, (dst)->icd.sz*((num) - (dst)->i)); \ - } \ - } \ - (dst)->i = (num); \ -} while(0) - -#define utarray_concat(dst,src) do { \ - utarray_inserta(dst, src, utarray_len(dst)); \ -} while(0) - -#define utarray_erase(a,pos,len) do { \ - if ((a)->icd.dtor) { \ - unsigned _ut_i; \ - for (_ut_i = 0; _ut_i < (len); _ut_i++) { \ - (a)->icd.dtor(utarray_eltptr(a, (pos) + _ut_i)); \ - } \ - } \ - if ((a)->i > ((pos) + (len))) { \ - memmove(_utarray_eltptr(a, pos), _utarray_eltptr(a, (pos) + (len)), \ - ((a)->i - ((pos) + (len))) * (a)->icd.sz); \ - } \ - (a)->i -= (len); \ -} while(0) - -#define utarray_renew(a,u) do { \ - if (a) utarray_clear(a); \ - else utarray_new(a, u); \ -} while(0) - -#define utarray_clear(a) do { \ - if ((a)->i > 0) { \ - if ((a)->icd.dtor) { \ - unsigned _ut_i; \ - for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \ - (a)->icd.dtor(_utarray_eltptr(a, _ut_i)); \ - } \ - } \ - (a)->i = 0; \ - } \ -} while(0) - -#define utarray_sort(a,cmp) do { \ - qsort((a)->d, (a)->i, (a)->icd.sz, cmp); \ -} while(0) - -#define utarray_find(a,v,cmp) bsearch((v),(a)->d,(a)->i,(a)->icd.sz,cmp) - -#define utarray_front(a) (((a)->i) ? (_utarray_eltptr(a,0)) : NULL) -#define utarray_next(a,e) (((e)==NULL) ? utarray_front(a) : (((a)->i != utarray_eltidx(a,e)+1) ? _utarray_eltptr(a,utarray_eltidx(a,e)+1) : NULL)) -#define utarray_prev(a,e) (((e)==NULL) ? utarray_back(a) : ((utarray_eltidx(a,e) != 0) ? _utarray_eltptr(a,utarray_eltidx(a,e)-1) : NULL)) -#define utarray_back(a) (((a)->i) ? (_utarray_eltptr(a,(a)->i-1)) : NULL) -#define utarray_eltidx(a,e) (((char*)(e) - (a)->d) / (a)->icd.sz) - -/* last we pre-define a few icd for common utarrays of ints and strings */ -static void utarray_str_cpy(void *dst, const void *src) { - char *const *srcc = (char *const *)src; - char **dstc = (char**)dst; - if (*srcc == NULL) { - *dstc = NULL; - } else { - *dstc = (char*)malloc(strlen(*srcc) + 1); - if (*dstc == NULL) { - utarray_oom(); - } else { - strcpy(*dstc, *srcc); - } - } -} -static void utarray_str_dtor(void *elt) { - char **eltc = (char**)elt; - if (*eltc != NULL) free(*eltc); -} -static const UT_icd ut_str_icd UTARRAY_UNUSED = {sizeof(char*),NULL,utarray_str_cpy,utarray_str_dtor}; -static const UT_icd ut_int_icd UTARRAY_UNUSED = {sizeof(int),NULL,NULL,NULL}; -static const UT_icd ut_ptr_icd UTARRAY_UNUSED = {sizeof(void*),NULL,NULL,NULL}; - - -#endif /* UTARRAY_H */ diff --git a/src/ocre/include/uthash/uthash.h b/src/ocre/include/uthash/uthash.h deleted file mode 100644 index 06c2eebd..00000000 --- a/src/ocre/include/uthash/uthash.h +++ /dev/null @@ -1,1137 +0,0 @@ -/* -Copyright (c) 2003-2025, Troy D. Hanson https://troydhanson.github.io/uthash/ -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef UTHASH_H -#define UTHASH_H - -#define UTHASH_VERSION 2.3.0 - -#include /* memcmp, memset, strlen */ -#include /* ptrdiff_t */ -#include /* exit */ - -#if defined(HASH_NO_STDINT) && HASH_NO_STDINT -/* The user doesn't have , and must figure out their own way - to provide definitions for uint8_t and uint32_t. */ -#else -#include /* uint8_t, uint32_t */ -#endif - -/* These macros use decltype or the earlier __typeof GNU extension. - As decltype is only available in newer compilers (VS2010 or gcc 4.3+ - when compiling c++ source) this code uses whatever method is needed - or, for VS2008 where neither is available, uses casting workarounds. */ -#if !defined(DECLTYPE) && !defined(NO_DECLTYPE) -#if defined(_MSC_VER) /* MS compiler */ -#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ -#define DECLTYPE(x) (decltype(x)) -#else /* VS2008 or older (or VS2010 in C mode) */ -#define NO_DECLTYPE -#endif -#elif defined(__MCST__) /* Elbrus C Compiler */ -#define DECLTYPE(x) (__typeof(x)) -#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__) -#define NO_DECLTYPE -#else /* GNU, Sun and other compilers */ -#define DECLTYPE(x) (__typeof(x)) -#endif -#endif - -#ifdef NO_DECLTYPE -#define DECLTYPE(x) -#define DECLTYPE_ASSIGN(dst,src) \ -do { \ - char **_da_dst = (char**)(&(dst)); \ - *_da_dst = (char*)(src); \ -} while (0) -#else -#define DECLTYPE_ASSIGN(dst,src) \ -do { \ - (dst) = DECLTYPE(dst)(src); \ -} while (0) -#endif - -#ifndef uthash_malloc -#define uthash_malloc(sz) malloc(sz) /* malloc fcn */ -#endif -#ifndef uthash_free -#define uthash_free(ptr,sz) free(ptr) /* free fcn */ -#endif -#ifndef uthash_bzero -#define uthash_bzero(a,n) memset(a,'\0',n) -#endif -#ifndef uthash_strlen -#define uthash_strlen(s) strlen(s) -#endif - -#ifndef HASH_FUNCTION -#define HASH_FUNCTION(keyptr,keylen,hashv) HASH_JEN(keyptr, keylen, hashv) -#endif - -#ifndef HASH_KEYCMP -#define HASH_KEYCMP(a,b,n) memcmp(a,b,n) -#endif - -#ifndef uthash_noexpand_fyi -#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ -#endif -#ifndef uthash_expand_fyi -#define uthash_expand_fyi(tbl) /* can be defined to log expands */ -#endif - -#ifndef HASH_NONFATAL_OOM -#define HASH_NONFATAL_OOM 0 -#endif - -#if HASH_NONFATAL_OOM -/* malloc failures can be recovered from */ - -#ifndef uthash_nonfatal_oom -#define uthash_nonfatal_oom(obj) do {} while (0) /* non-fatal OOM error */ -#endif - -#define HASH_RECORD_OOM(oomed) do { (oomed) = 1; } while (0) -#define IF_HASH_NONFATAL_OOM(x) x - -#else -/* malloc failures result in lost memory, hash tables are unusable */ - -#ifndef uthash_fatal -#define uthash_fatal(msg) exit(-1) /* fatal OOM error */ -#endif - -#define HASH_RECORD_OOM(oomed) uthash_fatal("out of memory") -#define IF_HASH_NONFATAL_OOM(x) - -#endif - -/* initial number of buckets */ -#define HASH_INITIAL_NUM_BUCKETS 32U /* initial number of buckets */ -#define HASH_INITIAL_NUM_BUCKETS_LOG2 5U /* lg2 of initial number of buckets */ -#define HASH_BKT_CAPACITY_THRESH 10U /* expand when bucket count reaches */ - -/* calculate the element whose hash handle address is hhp */ -#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho))) -/* calculate the hash handle from element address elp */ -#define HH_FROM_ELMT(tbl,elp) ((UT_hash_handle*)(void*)(((char*)(elp)) + ((tbl)->hho))) - -#define HASH_ROLLBACK_BKT(hh, head, itemptrhh) \ -do { \ - struct UT_hash_handle *_hd_hh_item = (itemptrhh); \ - unsigned _hd_bkt; \ - HASH_TO_BKT(_hd_hh_item->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ - (head)->hh.tbl->buckets[_hd_bkt].count++; \ - _hd_hh_item->hh_next = NULL; \ - _hd_hh_item->hh_prev = NULL; \ -} while (0) - -#define HASH_VALUE(keyptr,keylen,hashv) \ -do { \ - HASH_FUNCTION(keyptr, keylen, hashv); \ -} while (0) - -#define HASH_FIND_BYHASHVALUE(hh,head,keyptr,keylen,hashval,out) \ -do { \ - (out) = NULL; \ - if (head) { \ - unsigned _hf_bkt; \ - HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _hf_bkt); \ - if (HASH_BLOOM_TEST((head)->hh.tbl, hashval)) { \ - HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], keyptr, keylen, hashval, out); \ - } \ - } \ -} while (0) - -#define HASH_FIND(hh,head,keyptr,keylen,out) \ -do { \ - (out) = NULL; \ - if (head) { \ - unsigned _hf_hashv; \ - HASH_VALUE(keyptr, keylen, _hf_hashv); \ - HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, out); \ - } \ -} while (0) - -#ifdef HASH_BLOOM -#define HASH_BLOOM_BITLEN (1UL << HASH_BLOOM) -#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8UL) + (((HASH_BLOOM_BITLEN%8UL)!=0UL) ? 1UL : 0UL) -#define HASH_BLOOM_MAKE(tbl,oomed) \ -do { \ - (tbl)->bloom_nbits = HASH_BLOOM; \ - (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \ - if (!(tbl)->bloom_bv) { \ - HASH_RECORD_OOM(oomed); \ - } else { \ - uthash_bzero((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ - (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ - } \ -} while (0) - -#define HASH_BLOOM_FREE(tbl) \ -do { \ - uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ -} while (0) - -#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8U] |= (1U << ((idx)%8U))) -#define HASH_BLOOM_BITTEST(bv,idx) ((bv[(idx)/8U] & (1U << ((idx)%8U))) != 0) - -#define HASH_BLOOM_ADD(tbl,hashv) \ - HASH_BLOOM_BITSET((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U))) - -#define HASH_BLOOM_TEST(tbl,hashv) \ - HASH_BLOOM_BITTEST((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U))) - -#else -#define HASH_BLOOM_MAKE(tbl,oomed) -#define HASH_BLOOM_FREE(tbl) -#define HASH_BLOOM_ADD(tbl,hashv) -#define HASH_BLOOM_TEST(tbl,hashv) 1 -#define HASH_BLOOM_BYTELEN 0U -#endif - -#define HASH_MAKE_TABLE(hh,head,oomed) \ -do { \ - (head)->hh.tbl = (UT_hash_table*)uthash_malloc(sizeof(UT_hash_table)); \ - if (!(head)->hh.tbl) { \ - HASH_RECORD_OOM(oomed); \ - } else { \ - uthash_bzero((head)->hh.tbl, sizeof(UT_hash_table)); \ - (head)->hh.tbl->tail = &((head)->hh); \ - (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ - (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ - (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \ - (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \ - HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \ - (head)->hh.tbl->signature = HASH_SIGNATURE; \ - if (!(head)->hh.tbl->buckets) { \ - HASH_RECORD_OOM(oomed); \ - uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ - } else { \ - uthash_bzero((head)->hh.tbl->buckets, \ - HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \ - HASH_BLOOM_MAKE((head)->hh.tbl, oomed); \ - IF_HASH_NONFATAL_OOM( \ - if (oomed) { \ - uthash_free((head)->hh.tbl->buckets, \ - HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ - uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ - } \ - ) \ - } \ - } \ -} while (0) - -#define HASH_REPLACE_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,replaced,cmpfcn) \ -do { \ - (replaced) = NULL; \ - HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ - if (replaced) { \ - HASH_DELETE(hh, head, replaced); \ - } \ - HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn); \ -} while (0) - -#define HASH_REPLACE_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add,replaced) \ -do { \ - (replaced) = NULL; \ - HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ - if (replaced) { \ - HASH_DELETE(hh, head, replaced); \ - } \ - HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add); \ -} while (0) - -#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \ -do { \ - unsigned _hr_hashv; \ - HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ - HASH_REPLACE_BYHASHVALUE(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced); \ -} while (0) - -#define HASH_REPLACE_INORDER(hh,head,fieldname,keylen_in,add,replaced,cmpfcn) \ -do { \ - unsigned _hr_hashv; \ - HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ - HASH_REPLACE_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced, cmpfcn); \ -} while (0) - -#define HASH_APPEND_LIST(hh, head, add) \ -do { \ - (add)->hh.next = NULL; \ - (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ - (head)->hh.tbl->tail->next = (add); \ - (head)->hh.tbl->tail = &((add)->hh); \ -} while (0) - -#define HASH_AKBI_INNER_LOOP(hh,head,add,cmpfcn) \ -do { \ - do { \ - if (cmpfcn(DECLTYPE(head)(_hs_iter), add) > 0) { \ - break; \ - } \ - } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \ -} while (0) - -#ifdef NO_DECLTYPE -#undef HASH_AKBI_INNER_LOOP -#define HASH_AKBI_INNER_LOOP(hh,head,add,cmpfcn) \ -do { \ - char *_hs_saved_head = (char*)(head); \ - do { \ - DECLTYPE_ASSIGN(head, _hs_iter); \ - if (cmpfcn(head, add) > 0) { \ - DECLTYPE_ASSIGN(head, _hs_saved_head); \ - break; \ - } \ - DECLTYPE_ASSIGN(head, _hs_saved_head); \ - } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \ -} while (0) -#endif - -#if HASH_NONFATAL_OOM - -#define HASH_ADD_TO_TABLE(hh,head,keyptr,keylen_in,hashval,add,oomed) \ -do { \ - if (!(oomed)) { \ - unsigned _ha_bkt; \ - (head)->hh.tbl->num_items++; \ - HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ - HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \ - if (oomed) { \ - HASH_ROLLBACK_BKT(hh, head, &(add)->hh); \ - HASH_DELETE_HH(hh, head, &(add)->hh); \ - (add)->hh.tbl = NULL; \ - uthash_nonfatal_oom(add); \ - } else { \ - HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ - HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ - } \ - } else { \ - (add)->hh.tbl = NULL; \ - uthash_nonfatal_oom(add); \ - } \ -} while (0) - -#else - -#define HASH_ADD_TO_TABLE(hh,head,keyptr,keylen_in,hashval,add,oomed) \ -do { \ - unsigned _ha_bkt; \ - (head)->hh.tbl->num_items++; \ - HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ - HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \ - HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ - HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ -} while (0) - -#endif - - -#define HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh,head,keyptr,keylen_in,hashval,add,cmpfcn) \ -do { \ - IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \ - (add)->hh.hashv = (hashval); \ - (add)->hh.key = (char*) (keyptr); \ - (add)->hh.keylen = (unsigned) (keylen_in); \ - if (!(head)) { \ - (add)->hh.next = NULL; \ - (add)->hh.prev = NULL; \ - HASH_MAKE_TABLE(hh, add, _ha_oomed); \ - IF_HASH_NONFATAL_OOM( if (!_ha_oomed) { ) \ - (head) = (add); \ - IF_HASH_NONFATAL_OOM( } ) \ - } else { \ - void *_hs_iter = (head); \ - (add)->hh.tbl = (head)->hh.tbl; \ - HASH_AKBI_INNER_LOOP(hh, head, add, cmpfcn); \ - if (_hs_iter) { \ - (add)->hh.next = _hs_iter; \ - if (((add)->hh.prev = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev)) { \ - HH_FROM_ELMT((head)->hh.tbl, (add)->hh.prev)->next = (add); \ - } else { \ - (head) = (add); \ - } \ - HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev = (add); \ - } else { \ - HASH_APPEND_LIST(hh, head, add); \ - } \ - } \ - HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \ - HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE_INORDER"); \ -} while (0) - -#define HASH_ADD_KEYPTR_INORDER(hh,head,keyptr,keylen_in,add,cmpfcn) \ -do { \ - unsigned _hs_hashv; \ - HASH_VALUE(keyptr, keylen_in, _hs_hashv); \ - HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, keyptr, keylen_in, _hs_hashv, add, cmpfcn); \ -} while (0) - -#define HASH_ADD_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,cmpfcn) \ - HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn) - -#define HASH_ADD_INORDER(hh,head,fieldname,keylen_in,add,cmpfcn) \ - HASH_ADD_KEYPTR_INORDER(hh, head, &((add)->fieldname), keylen_in, add, cmpfcn) - -#define HASH_ADD_KEYPTR_BYHASHVALUE(hh,head,keyptr,keylen_in,hashval,add) \ -do { \ - IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \ - (add)->hh.hashv = (hashval); \ - (add)->hh.key = (const void*) (keyptr); \ - (add)->hh.keylen = (unsigned) (keylen_in); \ - if (!(head)) { \ - (add)->hh.next = NULL; \ - (add)->hh.prev = NULL; \ - HASH_MAKE_TABLE(hh, add, _ha_oomed); \ - IF_HASH_NONFATAL_OOM( if (!_ha_oomed) { ) \ - (head) = (add); \ - IF_HASH_NONFATAL_OOM( } ) \ - } else { \ - (add)->hh.tbl = (head)->hh.tbl; \ - HASH_APPEND_LIST(hh, head, add); \ - } \ - HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \ - HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE"); \ -} while (0) - -#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \ -do { \ - unsigned _ha_hashv; \ - HASH_VALUE(keyptr, keylen_in, _ha_hashv); \ - HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, keyptr, keylen_in, _ha_hashv, add); \ -} while (0) - -#define HASH_ADD_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add) \ - HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add) - -#define HASH_ADD(hh,head,fieldname,keylen_in,add) \ - HASH_ADD_KEYPTR(hh, head, &((add)->fieldname), keylen_in, add) - -#define HASH_TO_BKT(hashv,num_bkts,bkt) \ -do { \ - bkt = ((hashv) & ((num_bkts) - 1U)); \ -} while (0) - -/* delete "delptr" from the hash table. - * "the usual" patch-up process for the app-order doubly-linked-list. - * The use of _hd_hh_del below deserves special explanation. - * These used to be expressed using (delptr) but that led to a bug - * if someone used the same symbol for the head and deletee, like - * HASH_DELETE(hh,users,users); - * We want that to work, but by changing the head (users) below - * we were forfeiting our ability to further refer to the deletee (users) - * in the patch-up process. Solution: use scratch space to - * copy the deletee pointer, then the latter references are via that - * scratch pointer rather than through the repointed (users) symbol. - */ -#define HASH_DELETE(hh,head,delptr) \ - HASH_DELETE_HH(hh, head, &(delptr)->hh) - -#define HASH_DELETE_HH(hh,head,delptrhh) \ -do { \ - const struct UT_hash_handle *_hd_hh_del = (delptrhh); \ - if ((_hd_hh_del->prev == NULL) && (_hd_hh_del->next == NULL)) { \ - HASH_BLOOM_FREE((head)->hh.tbl); \ - uthash_free((head)->hh.tbl->buckets, \ - (head)->hh.tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ - uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ - (head) = NULL; \ - } else { \ - unsigned _hd_bkt; \ - if (_hd_hh_del == (head)->hh.tbl->tail) { \ - (head)->hh.tbl->tail = HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev); \ - } \ - if (_hd_hh_del->prev != NULL) { \ - HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev)->next = _hd_hh_del->next; \ - } else { \ - DECLTYPE_ASSIGN(head, _hd_hh_del->next); \ - } \ - if (_hd_hh_del->next != NULL) { \ - HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->next)->prev = _hd_hh_del->prev; \ - } \ - HASH_TO_BKT(_hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ - HASH_DEL_IN_BKT((head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ - (head)->hh.tbl->num_items--; \ - } \ - HASH_FSCK(hh, head, "HASH_DELETE_HH"); \ -} while (0) - -/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */ -#define HASH_FIND_STR(head,findstr,out) \ -do { \ - unsigned _uthash_hfstr_keylen = (unsigned)uthash_strlen(findstr); \ - HASH_FIND(hh, head, findstr, _uthash_hfstr_keylen, out); \ -} while (0) -#define HASH_ADD_STR(head,strfield,add) \ -do { \ - unsigned _uthash_hastr_keylen = (unsigned)uthash_strlen((add)->strfield); \ - HASH_ADD(hh, head, strfield[0], _uthash_hastr_keylen, add); \ -} while (0) -#define HASH_REPLACE_STR(head,strfield,add,replaced) \ -do { \ - unsigned _uthash_hrstr_keylen = (unsigned)uthash_strlen((add)->strfield); \ - HASH_REPLACE(hh, head, strfield[0], _uthash_hrstr_keylen, add, replaced); \ -} while (0) -#define HASH_FIND_INT(head,findint,out) \ - HASH_FIND(hh,head,findint,sizeof(int),out) -#define HASH_ADD_INT(head,intfield,add) \ - HASH_ADD(hh,head,intfield,sizeof(int),add) -#define HASH_REPLACE_INT(head,intfield,add,replaced) \ - HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced) -#define HASH_FIND_PTR(head,findptr,out) \ - HASH_FIND(hh,head,findptr,sizeof(void *),out) -#define HASH_ADD_PTR(head,ptrfield,add) \ - HASH_ADD(hh,head,ptrfield,sizeof(void *),add) -#define HASH_REPLACE_PTR(head,ptrfield,add,replaced) \ - HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced) -#define HASH_DEL(head,delptr) \ - HASH_DELETE(hh,head,delptr) - -/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined. - * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined. - */ -#ifdef HASH_DEBUG -#include /* fprintf, stderr */ -#define HASH_OOPS(...) do { fprintf(stderr, __VA_ARGS__); exit(-1); } while (0) -#define HASH_FSCK(hh,head,where) \ -do { \ - struct UT_hash_handle *_thh; \ - if (head) { \ - unsigned _bkt_i; \ - unsigned _count = 0; \ - char *_prev; \ - for (_bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; ++_bkt_i) { \ - unsigned _bkt_count = 0; \ - _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ - _prev = NULL; \ - while (_thh) { \ - if (_prev != (char*)(_thh->hh_prev)) { \ - HASH_OOPS("%s: invalid hh_prev %p, actual %p\n", \ - (where), (void*)_thh->hh_prev, (void*)_prev); \ - } \ - _bkt_count++; \ - _prev = (char*)(_thh); \ - _thh = _thh->hh_next; \ - } \ - _count += _bkt_count; \ - if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \ - HASH_OOPS("%s: invalid bucket count %u, actual %u\n", \ - (where), (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ - } \ - } \ - if (_count != (head)->hh.tbl->num_items) { \ - HASH_OOPS("%s: invalid hh item count %u, actual %u\n", \ - (where), (head)->hh.tbl->num_items, _count); \ - } \ - _count = 0; \ - _prev = NULL; \ - _thh = &(head)->hh; \ - while (_thh) { \ - _count++; \ - if (_prev != (char*)_thh->prev) { \ - HASH_OOPS("%s: invalid prev %p, actual %p\n", \ - (where), (void*)_thh->prev, (void*)_prev); \ - } \ - _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \ - _thh = (_thh->next ? HH_FROM_ELMT((head)->hh.tbl, _thh->next) : NULL); \ - } \ - if (_count != (head)->hh.tbl->num_items) { \ - HASH_OOPS("%s: invalid app item count %u, actual %u\n", \ - (where), (head)->hh.tbl->num_items, _count); \ - } \ - } \ -} while (0) -#else -#define HASH_FSCK(hh,head,where) -#endif - -/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to - * the descriptor to which this macro is defined for tuning the hash function. - * The app can #include to get the prototype for write(2). */ -#ifdef HASH_EMIT_KEYS -#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \ -do { \ - unsigned _klen = fieldlen; \ - write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ - write(HASH_EMIT_KEYS, keyptr, (unsigned long)fieldlen); \ -} while (0) -#else -#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) -#endif - -/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */ -#define HASH_BER(key,keylen,hashv) \ -do { \ - unsigned _hb_keylen = (unsigned)keylen; \ - const unsigned char *_hb_key = (const unsigned char*)(key); \ - (hashv) = 0; \ - while (_hb_keylen-- != 0U) { \ - (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; \ - } \ -} while (0) - - -/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at - * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx - * (archive link: https://archive.is/Ivcan ) - */ -#define HASH_SAX(key,keylen,hashv) \ -do { \ - unsigned _sx_i; \ - const unsigned char *_hs_key = (const unsigned char*)(key); \ - hashv = 0; \ - for (_sx_i=0; _sx_i < keylen; _sx_i++) { \ - hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ - } \ -} while (0) -/* FNV-1a variation */ -#define HASH_FNV(key,keylen,hashv) \ -do { \ - unsigned _fn_i; \ - const unsigned char *_hf_key = (const unsigned char*)(key); \ - (hashv) = 2166136261U; \ - for (_fn_i=0; _fn_i < keylen; _fn_i++) { \ - hashv = hashv ^ _hf_key[_fn_i]; \ - hashv = hashv * 16777619U; \ - } \ -} while (0) - -#define HASH_OAT(key,keylen,hashv) \ -do { \ - unsigned _ho_i; \ - const unsigned char *_ho_key=(const unsigned char*)(key); \ - hashv = 0; \ - for(_ho_i=0; _ho_i < keylen; _ho_i++) { \ - hashv += _ho_key[_ho_i]; \ - hashv += (hashv << 10); \ - hashv ^= (hashv >> 6); \ - } \ - hashv += (hashv << 3); \ - hashv ^= (hashv >> 11); \ - hashv += (hashv << 15); \ -} while (0) - -#define HASH_JEN_MIX(a,b,c) \ -do { \ - a -= b; a -= c; a ^= ( c >> 13 ); \ - b -= c; b -= a; b ^= ( a << 8 ); \ - c -= a; c -= b; c ^= ( b >> 13 ); \ - a -= b; a -= c; a ^= ( c >> 12 ); \ - b -= c; b -= a; b ^= ( a << 16 ); \ - c -= a; c -= b; c ^= ( b >> 5 ); \ - a -= b; a -= c; a ^= ( c >> 3 ); \ - b -= c; b -= a; b ^= ( a << 10 ); \ - c -= a; c -= b; c ^= ( b >> 15 ); \ -} while (0) - -#define HASH_JEN(key,keylen,hashv) \ -do { \ - unsigned _hj_i,_hj_j,_hj_k; \ - unsigned const char *_hj_key=(unsigned const char*)(key); \ - hashv = 0xfeedbeefu; \ - _hj_i = _hj_j = 0x9e3779b9u; \ - _hj_k = (unsigned)(keylen); \ - while (_hj_k >= 12U) { \ - _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \ - + ( (unsigned)_hj_key[2] << 16 ) \ - + ( (unsigned)_hj_key[3] << 24 ) ); \ - _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \ - + ( (unsigned)_hj_key[6] << 16 ) \ - + ( (unsigned)_hj_key[7] << 24 ) ); \ - hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \ - + ( (unsigned)_hj_key[10] << 16 ) \ - + ( (unsigned)_hj_key[11] << 24 ) ); \ - \ - HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ - \ - _hj_key += 12; \ - _hj_k -= 12U; \ - } \ - hashv += (unsigned)(keylen); \ - switch ( _hj_k ) { \ - case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); /* FALLTHROUGH */ \ - case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); /* FALLTHROUGH */ \ - case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); /* FALLTHROUGH */ \ - case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); /* FALLTHROUGH */ \ - case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); /* FALLTHROUGH */ \ - case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); /* FALLTHROUGH */ \ - case 5: _hj_j += _hj_key[4]; /* FALLTHROUGH */ \ - case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); /* FALLTHROUGH */ \ - case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); /* FALLTHROUGH */ \ - case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); /* FALLTHROUGH */ \ - case 1: _hj_i += _hj_key[0]; /* FALLTHROUGH */ \ - default: ; \ - } \ - HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ -} while (0) - -/* The Paul Hsieh hash function */ -#undef get16bits -#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ - || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) -#define get16bits(d) (*((const uint16_t *) (d))) -#endif - -#if !defined (get16bits) -#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \ - +(uint32_t)(((const uint8_t *)(d))[0]) ) -#endif -#define HASH_SFH(key,keylen,hashv) \ -do { \ - unsigned const char *_sfh_key=(unsigned const char*)(key); \ - uint32_t _sfh_tmp, _sfh_len = (uint32_t)keylen; \ - \ - unsigned _sfh_rem = _sfh_len & 3U; \ - _sfh_len >>= 2; \ - hashv = 0xcafebabeu; \ - \ - /* Main loop */ \ - for (;_sfh_len > 0U; _sfh_len--) { \ - hashv += get16bits (_sfh_key); \ - _sfh_tmp = ((uint32_t)(get16bits (_sfh_key+2)) << 11) ^ hashv; \ - hashv = (hashv << 16) ^ _sfh_tmp; \ - _sfh_key += 2U*sizeof (uint16_t); \ - hashv += hashv >> 11; \ - } \ - \ - /* Handle end cases */ \ - switch (_sfh_rem) { \ - case 3: hashv += get16bits (_sfh_key); \ - hashv ^= hashv << 16; \ - hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)]) << 18; \ - hashv += hashv >> 11; \ - break; \ - case 2: hashv += get16bits (_sfh_key); \ - hashv ^= hashv << 11; \ - hashv += hashv >> 17; \ - break; \ - case 1: hashv += *_sfh_key; \ - hashv ^= hashv << 10; \ - hashv += hashv >> 1; \ - break; \ - default: ; \ - } \ - \ - /* Force "avalanching" of final 127 bits */ \ - hashv ^= hashv << 3; \ - hashv += hashv >> 5; \ - hashv ^= hashv << 4; \ - hashv += hashv >> 17; \ - hashv ^= hashv << 25; \ - hashv += hashv >> 6; \ -} while (0) - -/* iterate over items in a known bucket to find desired item */ -#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,hashval,out) \ -do { \ - if ((head).hh_head != NULL) { \ - DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (head).hh_head)); \ - } else { \ - (out) = NULL; \ - } \ - while ((out) != NULL) { \ - if ((out)->hh.hashv == (hashval) && (out)->hh.keylen == (keylen_in)) { \ - if (HASH_KEYCMP((out)->hh.key, keyptr, keylen_in) == 0) { \ - break; \ - } \ - } \ - if ((out)->hh.hh_next != NULL) { \ - DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (out)->hh.hh_next)); \ - } else { \ - (out) = NULL; \ - } \ - } \ -} while (0) - -/* add an item to a bucket */ -#define HASH_ADD_TO_BKT(head,hh,addhh,oomed) \ -do { \ - UT_hash_bucket *_ha_head = &(head); \ - _ha_head->count++; \ - (addhh)->hh_next = _ha_head->hh_head; \ - (addhh)->hh_prev = NULL; \ - if (_ha_head->hh_head != NULL) { \ - _ha_head->hh_head->hh_prev = (addhh); \ - } \ - _ha_head->hh_head = (addhh); \ - if ((_ha_head->count >= ((_ha_head->expand_mult + 1U) * HASH_BKT_CAPACITY_THRESH)) \ - && !(addhh)->tbl->noexpand) { \ - HASH_EXPAND_BUCKETS(addhh,(addhh)->tbl, oomed); \ - IF_HASH_NONFATAL_OOM( \ - if (oomed) { \ - HASH_DEL_IN_BKT(head,addhh); \ - } \ - ) \ - } \ -} while (0) - -/* remove an item from a given bucket */ -#define HASH_DEL_IN_BKT(head,delhh) \ -do { \ - UT_hash_bucket *_hd_head = &(head); \ - _hd_head->count--; \ - if (_hd_head->hh_head == (delhh)) { \ - _hd_head->hh_head = (delhh)->hh_next; \ - } \ - if ((delhh)->hh_prev) { \ - (delhh)->hh_prev->hh_next = (delhh)->hh_next; \ - } \ - if ((delhh)->hh_next) { \ - (delhh)->hh_next->hh_prev = (delhh)->hh_prev; \ - } \ -} while (0) - -/* Bucket expansion has the effect of doubling the number of buckets - * and redistributing the items into the new buckets. Ideally the - * items will distribute more or less evenly into the new buckets - * (the extent to which this is true is a measure of the quality of - * the hash function as it applies to the key domain). - * - * With the items distributed into more buckets, the chain length - * (item count) in each bucket is reduced. Thus by expanding buckets - * the hash keeps a bound on the chain length. This bounded chain - * length is the essence of how a hash provides constant time lookup. - * - * The calculation of tbl->ideal_chain_maxlen below deserves some - * explanation. First, keep in mind that we're calculating the ideal - * maximum chain length based on the *new* (doubled) bucket count. - * In fractions this is just n/b (n=number of items,b=new num buckets). - * Since the ideal chain length is an integer, we want to calculate - * ceil(n/b). We don't depend on floating point arithmetic in this - * hash, so to calculate ceil(n/b) with integers we could write - * - * ceil(n/b) = (n/b) + ((n%b)?1:0) - * - * and in fact a previous version of this hash did just that. - * But now we have improved things a bit by recognizing that b is - * always a power of two. We keep its base 2 log handy (call it lb), - * so now we can write this with a bit shift and logical AND: - * - * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0) - * - */ -#define HASH_EXPAND_BUCKETS(hh,tbl,oomed) \ -do { \ - unsigned _he_bkt; \ - unsigned _he_bkt_i; \ - struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ - UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ - _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \ - sizeof(struct UT_hash_bucket) * (tbl)->num_buckets * 2U); \ - if (!_he_new_buckets) { \ - HASH_RECORD_OOM(oomed); \ - } else { \ - uthash_bzero(_he_new_buckets, \ - sizeof(struct UT_hash_bucket) * (tbl)->num_buckets * 2U); \ - (tbl)->ideal_chain_maxlen = \ - ((tbl)->num_items >> ((tbl)->log2_num_buckets+1U)) + \ - ((((tbl)->num_items & (((tbl)->num_buckets*2U)-1U)) != 0U) ? 1U : 0U); \ - (tbl)->nonideal_items = 0; \ - for (_he_bkt_i = 0; _he_bkt_i < (tbl)->num_buckets; _he_bkt_i++) { \ - _he_thh = (tbl)->buckets[ _he_bkt_i ].hh_head; \ - while (_he_thh != NULL) { \ - _he_hh_nxt = _he_thh->hh_next; \ - HASH_TO_BKT(_he_thh->hashv, (tbl)->num_buckets * 2U, _he_bkt); \ - _he_newbkt = &(_he_new_buckets[_he_bkt]); \ - if (++(_he_newbkt->count) > (tbl)->ideal_chain_maxlen) { \ - (tbl)->nonideal_items++; \ - if (_he_newbkt->count > _he_newbkt->expand_mult * (tbl)->ideal_chain_maxlen) { \ - _he_newbkt->expand_mult++; \ - } \ - } \ - _he_thh->hh_prev = NULL; \ - _he_thh->hh_next = _he_newbkt->hh_head; \ - if (_he_newbkt->hh_head != NULL) { \ - _he_newbkt->hh_head->hh_prev = _he_thh; \ - } \ - _he_newbkt->hh_head = _he_thh; \ - _he_thh = _he_hh_nxt; \ - } \ - } \ - uthash_free((tbl)->buckets, (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \ - (tbl)->num_buckets *= 2U; \ - (tbl)->log2_num_buckets++; \ - (tbl)->buckets = _he_new_buckets; \ - (tbl)->ineff_expands = ((tbl)->nonideal_items > ((tbl)->num_items >> 1)) ? \ - ((tbl)->ineff_expands+1U) : 0U; \ - if ((tbl)->ineff_expands > 1U) { \ - (tbl)->noexpand = 1; \ - uthash_noexpand_fyi(tbl); \ - } \ - uthash_expand_fyi(tbl); \ - } \ -} while (0) - - -/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */ -/* Note that HASH_SORT assumes the hash handle name to be hh. - * HASH_SRT was added to allow the hash handle name to be passed in. */ -#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn) -#define HASH_SRT(hh,head,cmpfcn) \ -do { \ - unsigned _hs_i; \ - unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \ - struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ - if (head != NULL) { \ - _hs_insize = 1; \ - _hs_looping = 1; \ - _hs_list = &((head)->hh); \ - while (_hs_looping != 0U) { \ - _hs_p = _hs_list; \ - _hs_list = NULL; \ - _hs_tail = NULL; \ - _hs_nmerges = 0; \ - while (_hs_p != NULL) { \ - _hs_nmerges++; \ - _hs_q = _hs_p; \ - _hs_psize = 0; \ - for (_hs_i = 0; _hs_i < _hs_insize; ++_hs_i) { \ - _hs_psize++; \ - _hs_q = ((_hs_q->next != NULL) ? \ - HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ - if (_hs_q == NULL) { \ - break; \ - } \ - } \ - _hs_qsize = _hs_insize; \ - while ((_hs_psize != 0U) || ((_hs_qsize != 0U) && (_hs_q != NULL))) { \ - if (_hs_psize == 0U) { \ - _hs_e = _hs_q; \ - _hs_q = ((_hs_q->next != NULL) ? \ - HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ - _hs_qsize--; \ - } else if ((_hs_qsize == 0U) || (_hs_q == NULL)) { \ - _hs_e = _hs_p; \ - if (_hs_p != NULL) { \ - _hs_p = ((_hs_p->next != NULL) ? \ - HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL); \ - } \ - _hs_psize--; \ - } else if ((cmpfcn( \ - DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_p)), \ - DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_q)) \ - )) <= 0) { \ - _hs_e = _hs_p; \ - if (_hs_p != NULL) { \ - _hs_p = ((_hs_p->next != NULL) ? \ - HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL); \ - } \ - _hs_psize--; \ - } else { \ - _hs_e = _hs_q; \ - _hs_q = ((_hs_q->next != NULL) ? \ - HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ - _hs_qsize--; \ - } \ - if ( _hs_tail != NULL ) { \ - _hs_tail->next = ((_hs_e != NULL) ? \ - ELMT_FROM_HH((head)->hh.tbl, _hs_e) : NULL); \ - } else { \ - _hs_list = _hs_e; \ - } \ - if (_hs_e != NULL) { \ - _hs_e->prev = ((_hs_tail != NULL) ? \ - ELMT_FROM_HH((head)->hh.tbl, _hs_tail) : NULL); \ - } \ - _hs_tail = _hs_e; \ - } \ - _hs_p = _hs_q; \ - } \ - if (_hs_tail != NULL) { \ - _hs_tail->next = NULL; \ - } \ - if (_hs_nmerges <= 1U) { \ - _hs_looping = 0; \ - (head)->hh.tbl->tail = _hs_tail; \ - DECLTYPE_ASSIGN(head, ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ - } \ - _hs_insize *= 2U; \ - } \ - HASH_FSCK(hh, head, "HASH_SRT"); \ - } \ -} while (0) - -/* This function selects items from one hash into another hash. - * The end result is that the selected items have dual presence - * in both hashes. There is no copy of the items made; rather - * they are added into the new hash through a secondary hash - * hash handle that must be present in the structure. */ -#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ -do { \ - unsigned _src_bkt, _dst_bkt; \ - void *_last_elt = NULL, *_elt; \ - UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \ - ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \ - if ((src) != NULL) { \ - for (_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \ - for (_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \ - _src_hh != NULL; \ - _src_hh = _src_hh->hh_next) { \ - _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ - if (cond(_elt)) { \ - IF_HASH_NONFATAL_OOM( int _hs_oomed = 0; ) \ - _dst_hh = (UT_hash_handle*)(void*)(((char*)_elt) + _dst_hho); \ - _dst_hh->key = _src_hh->key; \ - _dst_hh->keylen = _src_hh->keylen; \ - _dst_hh->hashv = _src_hh->hashv; \ - _dst_hh->prev = _last_elt; \ - _dst_hh->next = NULL; \ - if (_last_elt_hh != NULL) { \ - _last_elt_hh->next = _elt; \ - } \ - if ((dst) == NULL) { \ - DECLTYPE_ASSIGN(dst, _elt); \ - HASH_MAKE_TABLE(hh_dst, dst, _hs_oomed); \ - IF_HASH_NONFATAL_OOM( \ - if (_hs_oomed) { \ - uthash_nonfatal_oom(_elt); \ - (dst) = NULL; \ - continue; \ - } \ - ) \ - } else { \ - _dst_hh->tbl = (dst)->hh_dst.tbl; \ - } \ - HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \ - HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt], hh_dst, _dst_hh, _hs_oomed); \ - (dst)->hh_dst.tbl->num_items++; \ - IF_HASH_NONFATAL_OOM( \ - if (_hs_oomed) { \ - HASH_ROLLBACK_BKT(hh_dst, dst, _dst_hh); \ - HASH_DELETE_HH(hh_dst, dst, _dst_hh); \ - _dst_hh->tbl = NULL; \ - uthash_nonfatal_oom(_elt); \ - continue; \ - } \ - ) \ - HASH_BLOOM_ADD(_dst_hh->tbl, _dst_hh->hashv); \ - _last_elt = _elt; \ - _last_elt_hh = _dst_hh; \ - } \ - } \ - } \ - } \ - HASH_FSCK(hh_dst, dst, "HASH_SELECT"); \ -} while (0) - -#define HASH_CLEAR(hh,head) \ -do { \ - if ((head) != NULL) { \ - HASH_BLOOM_FREE((head)->hh.tbl); \ - uthash_free((head)->hh.tbl->buckets, \ - (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \ - uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ - (head) = NULL; \ - } \ -} while (0) - -#define HASH_OVERHEAD(hh,head) \ - (((head) != NULL) ? ( \ - (size_t)(((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \ - ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \ - sizeof(UT_hash_table) + \ - (HASH_BLOOM_BYTELEN))) : 0U) - -#ifdef NO_DECLTYPE -#define HASH_ITER(hh,head,el,tmp) \ -for(((el)=(head)), ((*(char**)(&(tmp)))=(char*)((head!=NULL)?(head)->hh.next:NULL)); \ - (el) != NULL; ((el)=(tmp)), ((*(char**)(&(tmp)))=(char*)((tmp!=NULL)?(tmp)->hh.next:NULL))) -#else -#define HASH_ITER(hh,head,el,tmp) \ -for(((el)=(head)), ((tmp)=DECLTYPE(el)((head!=NULL)?(head)->hh.next:NULL)); \ - (el) != NULL; ((el)=(tmp)), ((tmp)=DECLTYPE(el)((tmp!=NULL)?(tmp)->hh.next:NULL))) -#endif - -/* obtain a count of items in the hash */ -#define HASH_COUNT(head) HASH_CNT(hh,head) -#define HASH_CNT(hh,head) ((head != NULL)?((head)->hh.tbl->num_items):0U) - -typedef struct UT_hash_bucket { - struct UT_hash_handle *hh_head; - unsigned count; - - /* expand_mult is normally set to 0. In this situation, the max chain length - * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If - * the bucket's chain exceeds this length, bucket expansion is triggered). - * However, setting expand_mult to a non-zero value delays bucket expansion - * (that would be triggered by additions to this particular bucket) - * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH. - * (The multiplier is simply expand_mult+1). The whole idea of this - * multiplier is to reduce bucket expansions, since they are expensive, in - * situations where we know that a particular bucket tends to be overused. - * It is better to let its chain length grow to a longer yet-still-bounded - * value, than to do an O(n) bucket expansion too often. - */ - unsigned expand_mult; - -} UT_hash_bucket; - -/* random signature used only to find hash tables in external analysis */ -#define HASH_SIGNATURE 0xa0111fe1u -#define HASH_BLOOM_SIGNATURE 0xb12220f2u - -typedef struct UT_hash_table { - UT_hash_bucket *buckets; - unsigned num_buckets, log2_num_buckets; - unsigned num_items; - struct UT_hash_handle *tail; /* tail hh in app order, for fast append */ - ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */ - - /* in an ideal situation (all buckets used equally), no bucket would have - * more than ceil(#items/#buckets) items. that's the ideal chain length. */ - unsigned ideal_chain_maxlen; - - /* nonideal_items is the number of items in the hash whose chain position - * exceeds the ideal chain maxlen. these items pay the penalty for an uneven - * hash distribution; reaching them in a chain traversal takes >ideal steps */ - unsigned nonideal_items; - - /* ineffective expands occur when a bucket doubling was performed, but - * afterward, more than half the items in the hash had nonideal chain - * positions. If this happens on two consecutive expansions we inhibit any - * further expansion, as it's not helping; this happens when the hash - * function isn't a good fit for the key domain. When expansion is inhibited - * the hash will still work, albeit no longer in constant time. */ - unsigned ineff_expands, noexpand; - - uint32_t signature; /* used only to find hash tables in external analysis */ -#ifdef HASH_BLOOM - uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ - uint8_t *bloom_bv; - uint8_t bloom_nbits; -#endif - -} UT_hash_table; - -typedef struct UT_hash_handle { - struct UT_hash_table *tbl; - void *prev; /* prev element in app order */ - void *next; /* next element in app order */ - struct UT_hash_handle *hh_prev; /* previous hh in bucket order */ - struct UT_hash_handle *hh_next; /* next hh in bucket order */ - const void *key; /* ptr to enclosing struct's key */ - unsigned keylen; /* enclosing struct's key len */ - unsigned hashv; /* result of hash-fcn(key) */ -} UT_hash_handle; - -#endif /* UTHASH_H */ diff --git a/src/ocre/include/uthash/utringbuffer.h b/src/ocre/include/uthash/utringbuffer.h deleted file mode 100644 index 3309aeba..00000000 --- a/src/ocre/include/uthash/utringbuffer.h +++ /dev/null @@ -1,108 +0,0 @@ -/* -Copyright (c) 2015-2025, Troy D. Hanson https://troydhanson.github.io/uthash/ -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/* a ring-buffer implementation using macros - */ -#ifndef UTRINGBUFFER_H -#define UTRINGBUFFER_H - -#define UTRINGBUFFER_VERSION 2.3.0 - -#include -#include -#include "utarray.h" // for "UT_icd" - -typedef struct { - unsigned i; /* index of next available slot; wraps at n */ - unsigned n; /* capacity */ - unsigned char f; /* full */ - UT_icd icd; /* initializer, copy and destructor functions */ - char *d; /* n slots of size icd->sz */ -} UT_ringbuffer; - -#define utringbuffer_init(a, _n, _icd) do { \ - memset(a, 0, sizeof(UT_ringbuffer)); \ - (a)->icd = *(_icd); \ - (a)->n = (_n); \ - if ((a)->n) { (a)->d = (char*)malloc((a)->n * (_icd)->sz); } \ -} while(0) - -#define utringbuffer_clear(a) do { \ - if ((a)->icd.dtor) { \ - if ((a)->f) { \ - unsigned _ut_i; \ - for (_ut_i = 0; _ut_i < (a)->n; ++_ut_i) { \ - (a)->icd.dtor(utringbuffer_eltptr(a, _ut_i)); \ - } \ - } else { \ - unsigned _ut_i; \ - for (_ut_i = 0; _ut_i < (a)->i; ++_ut_i) { \ - (a)->icd.dtor(utringbuffer_eltptr(a, _ut_i)); \ - } \ - } \ - } \ - (a)->i = 0; \ - (a)->f = 0; \ -} while(0) - -#define utringbuffer_done(a) do { \ - utringbuffer_clear(a); \ - free((a)->d); (a)->d = NULL; \ - (a)->n = 0; \ -} while(0) - -#define utringbuffer_new(a,n,_icd) do { \ - a = (UT_ringbuffer*)malloc(sizeof(UT_ringbuffer)); \ - utringbuffer_init(a, n, _icd); \ -} while(0) - -#define utringbuffer_free(a) do { \ - utringbuffer_done(a); \ - free(a); \ -} while(0) - -#define utringbuffer_push_back(a,p) do { \ - if ((a)->icd.dtor && (a)->f) { (a)->icd.dtor(_utringbuffer_internalptr(a,(a)->i)); } \ - if ((a)->icd.copy) { (a)->icd.copy( _utringbuffer_internalptr(a,(a)->i), p); } \ - else { memcpy(_utringbuffer_internalptr(a,(a)->i), p, (a)->icd.sz); }; \ - if (++(a)->i == (a)->n) { (a)->i = 0; (a)->f = 1; } \ -} while(0) - -#define utringbuffer_len(a) ((a)->f ? (a)->n : (a)->i) -#define utringbuffer_empty(a) ((a)->i == 0 && !(a)->f) -#define utringbuffer_full(a) ((a)->f != 0) - -#define _utringbuffer_real_idx(a,j) ((a)->f ? ((j) + (a)->i) % (a)->n : (j)) -#define _utringbuffer_internalptr(a,j) ((void*)((a)->d + ((a)->icd.sz * (j)))) -#define utringbuffer_eltptr(a,j) ((0 <= (j) && (j) < utringbuffer_len(a)) ? _utringbuffer_internalptr(a,_utringbuffer_real_idx(a,j)) : NULL) - -#define _utringbuffer_fake_idx(a,j) ((a)->f ? ((j) + (a)->n - (a)->i) % (a)->n : (j)) -#define _utringbuffer_internalidx(a,e) (((char*)(e) >= (a)->d) ? (((char*)(e) - (a)->d)/(a)->icd.sz) : -1) -#define utringbuffer_eltidx(a,e) _utringbuffer_fake_idx(a, _utringbuffer_internalidx(a,e)) - -#define utringbuffer_front(a) utringbuffer_eltptr(a,0) -#define utringbuffer_next(a,e) ((e)==NULL ? utringbuffer_front(a) : utringbuffer_eltptr(a, utringbuffer_eltidx(a,e)+1)) -#define utringbuffer_prev(a,e) ((e)==NULL ? utringbuffer_back(a) : utringbuffer_eltptr(a, utringbuffer_eltidx(a,e)-1)) -#define utringbuffer_back(a) (utringbuffer_empty(a) ? NULL : utringbuffer_eltptr(a, utringbuffer_len(a) - 1)) - -#endif /* UTRINGBUFFER_H */ diff --git a/src/ocre/include/uthash/utstack.h b/src/ocre/include/uthash/utstack.h deleted file mode 100644 index d71bcdb1..00000000 --- a/src/ocre/include/uthash/utstack.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -Copyright (c) 2018-2025, Troy D. Hanson https://troydhanson.github.io/uthash/ -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef UTSTACK_H -#define UTSTACK_H - -#define UTSTACK_VERSION 2.3.0 - -/* - * This file contains macros to manipulate a singly-linked list as a stack. - * - * To use utstack, your structure must have a "next" pointer. - * - * ----------------.EXAMPLE ------------------------- - * struct item { - * int id; - * struct item *next; - * }; - * - * struct item *stack = NULL; - * - * int main() { - * int count; - * struct item *tmp; - * struct item *item = malloc(sizeof *item); - * item->id = 42; - * STACK_COUNT(stack, tmp, count); assert(count == 0); - * STACK_PUSH(stack, item); - * STACK_COUNT(stack, tmp, count); assert(count == 1); - * STACK_POP(stack, item); - * free(item); - * STACK_COUNT(stack, tmp, count); assert(count == 0); - * } - * -------------------------------------------------- - */ - -#define STACK_TOP(head) (head) - -#define STACK_EMPTY(head) (!(head)) - -#define STACK_PUSH(head,add) \ - STACK_PUSH2(head,add,next) - -#define STACK_PUSH2(head,add,next) \ -do { \ - (add)->next = (head); \ - (head) = (add); \ -} while (0) - -#define STACK_POP(head,result) \ - STACK_POP2(head,result,next) - -#define STACK_POP2(head,result,next) \ -do { \ - (result) = (head); \ - (head) = (head)->next; \ -} while (0) - -#define STACK_COUNT(head,el,counter) \ - STACK_COUNT2(head,el,counter,next) \ - -#define STACK_COUNT2(head,el,counter,next) \ -do { \ - (counter) = 0; \ - for ((el) = (head); el; (el) = (el)->next) { ++(counter); } \ -} while (0) - -#endif /* UTSTACK_H */ diff --git a/src/ocre/include/uthash/utstring.h b/src/ocre/include/uthash/utstring.h deleted file mode 100644 index 264d5b4f..00000000 --- a/src/ocre/include/uthash/utstring.h +++ /dev/null @@ -1,407 +0,0 @@ -/* -Copyright (c) 2008-2025, Troy D. Hanson https://troydhanson.github.io/uthash/ -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/* a dynamic string implementation using macros - */ -#ifndef UTSTRING_H -#define UTSTRING_H - -#define UTSTRING_VERSION 2.3.0 - -#include -#include -#include -#include - -#ifdef __GNUC__ -#define UTSTRING_UNUSED __attribute__((__unused__)) -#else -#define UTSTRING_UNUSED -#endif - -#ifdef oom -#error "The name of macro 'oom' has been changed to 'utstring_oom'. Please update your code." -#define utstring_oom() oom() -#endif - -#ifndef utstring_oom -#define utstring_oom() exit(-1) -#endif - -typedef struct { - char *d; /* pointer to allocated buffer */ - size_t n; /* allocated capacity */ - size_t i; /* index of first unused byte */ -} UT_string; - -#define utstring_reserve(s,amt) \ -do { \ - if (((s)->n - (s)->i) < (size_t)(amt)) { \ - char *utstring_tmp = (char*)realloc( \ - (s)->d, (s)->n + (amt)); \ - if (!utstring_tmp) { \ - utstring_oom(); \ - } \ - (s)->d = utstring_tmp; \ - (s)->n += (amt); \ - } \ -} while(0) - -#define utstring_init(s) \ -do { \ - (s)->n = 0; (s)->i = 0; (s)->d = NULL; \ - utstring_reserve(s,100); \ - (s)->d[0] = '\0'; \ -} while(0) - -#define utstring_done(s) \ -do { \ - if ((s)->d != NULL) free((s)->d); \ - (s)->n = 0; \ -} while(0) - -#define utstring_free(s) \ -do { \ - utstring_done(s); \ - free(s); \ -} while(0) - -#define utstring_new(s) \ -do { \ - (s) = (UT_string*)malloc(sizeof(UT_string)); \ - if (!(s)) { \ - utstring_oom(); \ - } \ - utstring_init(s); \ -} while(0) - -#define utstring_renew(s) \ -do { \ - if (s) { \ - utstring_clear(s); \ - } else { \ - utstring_new(s); \ - } \ -} while(0) - -#define utstring_clear(s) \ -do { \ - (s)->i = 0; \ - (s)->d[0] = '\0'; \ -} while(0) - -#define utstring_bincpy(s,b,l) \ -do { \ - utstring_reserve((s),(l)+1); \ - if (l) memcpy(&(s)->d[(s)->i], b, l); \ - (s)->i += (l); \ - (s)->d[(s)->i]='\0'; \ -} while(0) - -#define utstring_concat(dst,src) \ -do { \ - utstring_reserve((dst),((src)->i)+1); \ - if ((src)->i) memcpy(&(dst)->d[(dst)->i], (src)->d, (src)->i); \ - (dst)->i += (src)->i; \ - (dst)->d[(dst)->i]='\0'; \ -} while(0) - -#define utstring_len(s) ((s)->i) - -#define utstring_body(s) ((s)->d) - -UTSTRING_UNUSED static void utstring_printf_va(UT_string *s, const char *fmt, va_list ap) { - int n; - va_list cp; - for (;;) { -#ifdef _WIN32 - cp = ap; -#else - va_copy(cp, ap); -#endif - n = vsnprintf(&s->d[s->i], s->n-s->i, fmt, cp); - va_end(cp); - - if ((n > -1) && ((size_t) n < (s->n-s->i))) { - s->i += n; - return; - } - - /* Else try again with more space. */ - if (n > -1) utstring_reserve(s,n+1); /* exact */ - else utstring_reserve(s,(s->n)*2); /* 2x */ - } -} -#ifdef __GNUC__ -/* support printf format checking (2=the format string, 3=start of varargs) */ -static void utstring_printf(UT_string *s, const char *fmt, ...) - __attribute__((format(printf, 2, 3))); -#endif -UTSTRING_UNUSED static void utstring_printf(UT_string *s, const char *fmt, ...) { - va_list ap; - va_start(ap,fmt); - utstring_printf_va(s,fmt,ap); - va_end(ap); -} - -/******************************************************************************* - * begin substring search functions * - ******************************************************************************/ -/* Build KMP table from left to right. */ -UTSTRING_UNUSED static void _utstring_BuildTable( - const char *P_Needle, - size_t P_NeedleLen, - long *P_KMP_Table) -{ - long i, j; - - i = 0; - j = i - 1; - P_KMP_Table[i] = j; - while (i < (long) P_NeedleLen) - { - while ( (j > -1) && (P_Needle[i] != P_Needle[j]) ) - { - j = P_KMP_Table[j]; - } - i++; - j++; - if (i < (long) P_NeedleLen) - { - if (P_Needle[i] == P_Needle[j]) - { - P_KMP_Table[i] = P_KMP_Table[j]; - } - else - { - P_KMP_Table[i] = j; - } - } - else - { - P_KMP_Table[i] = j; - } - } - - return; -} - - -/* Build KMP table from right to left. */ -UTSTRING_UNUSED static void _utstring_BuildTableR( - const char *P_Needle, - size_t P_NeedleLen, - long *P_KMP_Table) -{ - long i, j; - - i = P_NeedleLen - 1; - j = i + 1; - P_KMP_Table[i + 1] = j; - while (i >= 0) - { - while ( (j < (long) P_NeedleLen) && (P_Needle[i] != P_Needle[j]) ) - { - j = P_KMP_Table[j + 1]; - } - i--; - j--; - if (i >= 0) - { - if (P_Needle[i] == P_Needle[j]) - { - P_KMP_Table[i + 1] = P_KMP_Table[j + 1]; - } - else - { - P_KMP_Table[i + 1] = j; - } - } - else - { - P_KMP_Table[i + 1] = j; - } - } - - return; -} - - -/* Search data from left to right. ( Multiple search mode. ) */ -UTSTRING_UNUSED static long _utstring_find( - const char *P_Haystack, - size_t P_HaystackLen, - const char *P_Needle, - size_t P_NeedleLen, - const long *P_KMP_Table) -{ - long i, j; - long V_FindPosition = -1; - - /* Search from left to right. */ - i = j = 0; - while ( (j < (int)P_HaystackLen) && (((P_HaystackLen - j) + i) >= P_NeedleLen) ) - { - while ( (i > -1) && (P_Needle[i] != P_Haystack[j]) ) - { - i = P_KMP_Table[i]; - } - i++; - j++; - if (i >= (int)P_NeedleLen) - { - /* Found. */ - V_FindPosition = j - i; - break; - } - } - - return V_FindPosition; -} - - -/* Search data from right to left. ( Multiple search mode. ) */ -UTSTRING_UNUSED static long _utstring_findR( - const char *P_Haystack, - size_t P_HaystackLen, - const char *P_Needle, - size_t P_NeedleLen, - const long *P_KMP_Table) -{ - long i, j; - long V_FindPosition = -1; - - /* Search from right to left. */ - j = (P_HaystackLen - 1); - i = (P_NeedleLen - 1); - while ( (j >= 0) && (j >= i) ) - { - while ( (i < (int)P_NeedleLen) && (P_Needle[i] != P_Haystack[j]) ) - { - i = P_KMP_Table[i + 1]; - } - i--; - j--; - if (i < 0) - { - /* Found. */ - V_FindPosition = j + 1; - break; - } - } - - return V_FindPosition; -} - - -/* Search data from left to right. ( One time search mode. ) */ -UTSTRING_UNUSED static long utstring_find( - const UT_string *s, - long P_StartPosition, /* Start from 0. -1 means last position. */ - const char *P_Needle, - size_t P_NeedleLen) -{ - long V_StartPosition; - long V_HaystackLen; - long *V_KMP_Table; - long V_FindPosition = -1; - - if (P_StartPosition < 0) - { - V_StartPosition = s->i + P_StartPosition; - } - else - { - V_StartPosition = P_StartPosition; - } - V_HaystackLen = s->i - V_StartPosition; - if ( (V_HaystackLen >= (long) P_NeedleLen) && (P_NeedleLen > 0) ) - { - V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1)); - if (V_KMP_Table != NULL) - { - _utstring_BuildTable(P_Needle, P_NeedleLen, V_KMP_Table); - - V_FindPosition = _utstring_find(s->d + V_StartPosition, - V_HaystackLen, - P_Needle, - P_NeedleLen, - V_KMP_Table); - if (V_FindPosition >= 0) - { - V_FindPosition += V_StartPosition; - } - - free(V_KMP_Table); - } - } - - return V_FindPosition; -} - - -/* Search data from right to left. ( One time search mode. ) */ -UTSTRING_UNUSED static long utstring_findR( - const UT_string *s, - long P_StartPosition, /* Start from 0. -1 means last position. */ - const char *P_Needle, - size_t P_NeedleLen) -{ - long V_StartPosition; - long V_HaystackLen; - long *V_KMP_Table; - long V_FindPosition = -1; - - if (P_StartPosition < 0) - { - V_StartPosition = s->i + P_StartPosition; - } - else - { - V_StartPosition = P_StartPosition; - } - V_HaystackLen = V_StartPosition + 1; - if ( (V_HaystackLen >= (long) P_NeedleLen) && (P_NeedleLen > 0) ) - { - V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1)); - if (V_KMP_Table != NULL) - { - _utstring_BuildTableR(P_Needle, P_NeedleLen, V_KMP_Table); - - V_FindPosition = _utstring_findR(s->d, - V_HaystackLen, - P_Needle, - P_NeedleLen, - V_KMP_Table); - - free(V_KMP_Table); - } - } - - return V_FindPosition; -} -/******************************************************************************* - * end substring search functions * - ******************************************************************************/ - -#endif /* UTSTRING_H */ From 156545d12149f8e4395487a31f9a30d8aff9d1c3 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 11 Dec 2025 19:28:11 +0100 Subject: [PATCH 090/234] chore(util/rm_rf): remove verbose function Signed-off-by: Marco Casaroli --- src/ocre/util/rm_rf.c | 147 ------------------------------------------ src/ocre/util/rm_rf.h | 34 ++-------- 2 files changed, 4 insertions(+), 177 deletions(-) diff --git a/src/ocre/util/rm_rf.c b/src/ocre/util/rm_rf.c index 0d73e579..abec6023 100644 --- a/src/ocre/util/rm_rf.c +++ b/src/ocre/util/rm_rf.c @@ -175,150 +175,3 @@ int rm_rf(const char *path) { return result; } - -/* Alternative version with more detailed error reporting */ -int rm_rf_verbose(const char *path, int (*error_callback)(const char *path, int error_code)) { - if (!path) { - if (error_callback) { - error_callback(path, EINVAL); - } - errno = EINVAL; - return -1; - } - - struct stat st; - if (stat(path, &st) == -1) { - if (error_callback) { - error_callback(path, errno); - } - return -1; - } - - /* If it's a regular file, just remove it */ - if (!S_ISDIR(st.st_mode)) { - if (unlink(path) == -1) { - if (error_callback) { - error_callback(path, errno); - } - return -1; - } - return 0; - } - - /* Stack for directory traversal */ - struct dir_stack_node *stack = NULL; - int result = 0; - - /* Push initial directory onto stack */ - stack = push_dir(stack, path, 0); - if (!stack) { - if (error_callback) { - error_callback(path, ENOMEM); - } - errno = ENOMEM; - return -1; - } - - /* Process stack until empty */ - while (stack) { - struct dir_stack_node *current = stack; - - if (current->is_removal_phase) { - /* This directory has been processed, now remove it */ - if (rmdir(current->path) == -1) { - if (error_callback) { - error_callback(current->path, errno); - } - result = -1; - } - stack = pop_dir(stack); - continue; - } - - /* First time processing this directory */ - if (!current->dir) { - current->dir = opendir(current->path); - if (!current->dir) { - if (error_callback) { - error_callback(current->path, errno); - } - result = -1; - stack = pop_dir(stack); - continue; - } - } - - /* Read next directory entry */ - errno = 0; /* Clear errno before readdir */ - struct dirent *entry = readdir(current->dir); - if (!entry) { - if (errno != 0) { - if (error_callback) { - error_callback(current->path, errno); - } - result = -1; - } - /* No more entries, mark for removal and continue */ - current->is_removal_phase = 1; - continue; - } - - /* Skip . and .. entries */ - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { - continue; - } - - /* Build full path for this entry */ - char *entry_path = build_path(current->path, entry->d_name); - if (!entry_path) { - if (error_callback) { - error_callback("memory allocation", ENOMEM); - } - result = -1; - errno = ENOMEM; - break; - } - - /* Get entry information */ - if (stat(entry_path, &st) == -1) { - if (error_callback) { - error_callback(entry_path, errno); - } - result = -1; - free(entry_path); - continue; - } - - if (S_ISDIR(st.st_mode)) { - /* It's a directory - push it onto stack for processing */ - struct dir_stack_node *new_node = push_dir(stack, entry_path, 0); - if (!new_node) { - if (error_callback) { - error_callback(entry_path, ENOMEM); - } - result = -1; - errno = ENOMEM; - free(entry_path); - break; - } - stack = new_node; - } else { - /* It's a file - remove it directly */ - if (unlink(entry_path) == -1) { - if (error_callback) { - error_callback(entry_path, errno); - } - result = -1; - } - } - - free(entry_path); - } - - /* Clean up remaining stack in case of error */ - while (stack) { - stack = pop_dir(stack); - } - - return result; -} diff --git a/src/ocre/util/rm_rf.h b/src/ocre/util/rm_rf.h index 6cfe36b0..fd3b9440 100644 --- a/src/ocre/util/rm_rf.h +++ b/src/ocre/util/rm_rf.h @@ -1,44 +1,18 @@ #ifndef RM_RF_H #define RM_RF_H -#ifdef __cplusplus -extern "C" { -#endif - /** * Remove a file or directory recursively. - * + * * This function removes the specified path and all its contents recursively. * It uses a stack-based approach to traverse directories without function recursion. - * + * * @param path The path to the file or directory to remove * @return 0 on success, -1 on error (errno is set appropriately) - * + * * Note: This function will attempt to remove as many files/directories as possible * even if some operations fail. The return value indicates if any errors occurred. */ int rm_rf(const char *path); -/** - * Remove a file or directory recursively with error callback. - * - * This function is similar to rm_rf() but provides detailed error reporting - * through a callback function that is called for each error encountered. - * - * @param path The path to the file or directory to remove - * @param error_callback Callback function called for each error. Should return 0 - * to continue processing, non-zero to abort. Can be NULL. - * Parameters: (const char *failed_path, int error_code) - * @return 0 on success, -1 on error (errno is set appropriately) - * - * The error_callback receives: - * - failed_path: The path that caused the error (or descriptive string for memory errors) - * - error_code: The errno value associated with the error - */ -int rm_rf_verbose(const char *path, int (*error_callback)(const char *path, int error_code)); - -#ifdef __cplusplus -} -#endif - -#endif /* RM_RF_H */ \ No newline at end of file +#endif /* RM_RF_H */ From e5dfcb56bb75691b4c69ec30116995cd2bb6d331 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 11 Dec 2025 19:28:42 +0100 Subject: [PATCH 091/234] chore(util/string_array): use C comments Signed-off-by: Marco Casaroli --- src/ocre/util/string_array.c | 6 ------ src/ocre/util/string_array.h | 24 ++++++++++++++++++++++++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/ocre/util/string_array.c b/src/ocre/util/string_array.c index 4d11446f..224c1aa4 100644 --- a/src/ocre/util/string_array.c +++ b/src/ocre/util/string_array.c @@ -4,8 +4,6 @@ #include "string_array.h" -// returns the size of a string array including the NULL termination -// returns 0 if pointer is null size_t string_array_size(const char **array) { size_t size = 0; @@ -21,8 +19,6 @@ size_t string_array_size(const char **array) return size; } -// duplicates an array of char * -// returns NULL on error char **string_array_dup(char **src) { size_t size = string_array_size((const char **)src); @@ -59,8 +55,6 @@ void string_array_free(char **array) free(array); } -// makes a deep copy of an array of char * -// returns NULL on error char **string_array_deep_dup(const char **const src) { size_t size = string_array_size((const char **)src); diff --git a/src/ocre/util/string_array.h b/src/ocre/util/string_array.h index 2fabaf65..0ba946c4 100644 --- a/src/ocre/util/string_array.h +++ b/src/ocre/util/string_array.h @@ -1,7 +1,31 @@ #include + +/* returns the size of a string array including the NULL termination + * returns 0 if pointer is null + */ size_t string_array_size(const char **const array); + +/* duplicates an array of char * + * returns NULL on error + */ char **string_array_dup(char **src); + +/* makes a deep copy of an array of char * + * returns NULL on error + */ char **string_array_deep_dup(const char **const src); + +/* frees an array of char * + * does nothing if pointer is null + */ void string_array_free(char **array); + +/* copies an array of char * + * returns the number of elements copied + */ size_t string_array_copy(char **dest, char **src); + +/* looks up a key in an array of char * + * returns NULL if not found + */ const char *string_array_lookup(const char **array, const char *key); From 9204ce3515ad4293463563e4c3ed3bb8afca8f2f Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 11 Dec 2025 19:30:54 +0100 Subject: [PATCH 092/234] chore(platform/posix): file map cleanup Signed-off-by: Marco Casaroli --- src/platform/posix/file_alloc_fread.c | 6 +----- src/platform/posix/file_alloc_read.c | 7 +------ 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/platform/posix/file_alloc_fread.c b/src/platform/posix/file_alloc_fread.c index 0c73c823..599ae068 100644 --- a/src/platform/posix/file_alloc_fread.c +++ b/src/platform/posix/file_alloc_fread.c @@ -41,9 +41,6 @@ void *ocre_load_file(const char *path, size_t *size) } size_t file_size = (size_t)finfo.st_size; - // - // size_t file_size = 100; - // LOG_INF("File size to load: %zu", file_size); @@ -60,9 +57,8 @@ void *ocre_load_file(const char *path, size_t *size) memset(buffer, 0, file_size); - // fseek(fp, 0, SEEK_SET); + /* Read from file into buffer */ - // read from file into buffer size_t bytes_read = fread(buffer, 1, file_size, fp); if (bytes_read != file_size) { diff --git a/src/platform/posix/file_alloc_read.c b/src/platform/posix/file_alloc_read.c index 956d3d51..f14c5bc2 100644 --- a/src/platform/posix/file_alloc_read.c +++ b/src/platform/posix/file_alloc_read.c @@ -1,7 +1,6 @@ #include #include #include -// #include #include #include @@ -34,9 +33,6 @@ void *ocre_load_file(const char *path, size_t *size) } ssize_t file_size = (ssize_t)finfo.st_size; - // - // size_t file_size = 100; - // LOG_INF("File size to load: %zu", file_size); @@ -53,9 +49,8 @@ void *ocre_load_file(const char *path, size_t *size) memset(buffer, 0, file_size); - // fseek(fp, 0, SEEK_SET); + /* Read from file into buffer */ - // read from file into buffer ssize_t bytes_read = read(fd, buffer, file_size); if (bytes_read != file_size) { From a75a15aa70919bb85fbff88ec3c629b2ef0bbc3a Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 11 Dec 2025 19:44:49 +0100 Subject: [PATCH 093/234] chore: formatting and remove spurious comments Signed-off-by: Marco Casaroli --- CMakeLists.txt | 3 +-- src/ocre/context.h | 3 --- src/ocre/include/ocre/ocre.h | 7 ------- src/samples/demo/zephyr/prj.conf | 2 +- src/samples/mini/posix/CMakeLists.txt | 1 - src/samples/mini/zephyr/prj.conf | 2 +- 6 files changed, 3 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 608a6618..ad651a8c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,6 @@ set(CMAKE_C_STANDARD 99) set(CMAKE_CXX_STANDARD 17) set(WAMR_BUILD_PLATFORM linux) -# set(WAMR_BUILD_PLATFORM darwin) include (src/samples/demo/demo_containers.cmake) @@ -35,7 +34,7 @@ add_subdirectory(src/runtime/wamr) add_subdirectory(src/platform/posix) # shell -#add_subdirectory(src/shell) +add_subdirectory(src/shell) # samples add_subdirectory(src/samples/mini/posix) diff --git a/src/ocre/context.h b/src/ocre/context.h index 1f959c0c..a170dd85 100644 --- a/src/ocre/context.h +++ b/src/ocre/context.h @@ -1,6 +1,3 @@ struct ocre_context; -// struct ocre_container *ocre_container_create(const char *path, const char *const runtime, const char *container_id, -// const void *arguments); -// void ocre_container_destroy(struct ocre_container *container); struct ocre_container *ocre_context_get_container_by_id_locked(const struct ocre_context *context, const char *id); diff --git a/src/ocre/include/ocre/ocre.h b/src/ocre/include/ocre/ocre.h index 5eb6b282..f344c277 100644 --- a/src/ocre/include/ocre/ocre.h +++ b/src/ocre/include/ocre/ocre.h @@ -36,13 +36,6 @@ struct ocre_container_args { const char **mounts; }; -// struct ocre_container_info { -// const char *id; -// const char *image; -// struct ocre_container_args args; -// int exit_code; -// }; - struct ocre_container; int ocre_initialize(void); diff --git a/src/samples/demo/zephyr/prj.conf b/src/samples/demo/zephyr/prj.conf index 74a2b4ec..938fa212 100644 --- a/src/samples/demo/zephyr/prj.conf +++ b/src/samples/demo/zephyr/prj.conf @@ -1,4 +1,4 @@ -#Logging +# Logging CONFIG_LOG=y CONFIG_LOG_MODE_MINIMAL=y diff --git a/src/samples/mini/posix/CMakeLists.txt b/src/samples/mini/posix/CMakeLists.txt index 3b8767af..6b53d72e 100644 --- a/src/samples/mini/posix/CMakeLists.txt +++ b/src/samples/mini/posix/CMakeLists.txt @@ -1,6 +1,5 @@ cmake_minimum_required(VERSION 3.20.0) - project (ocre_sample_mini) add_executable(ocre_mini diff --git a/src/samples/mini/zephyr/prj.conf b/src/samples/mini/zephyr/prj.conf index 5f06db51..faa4534c 100644 --- a/src/samples/mini/zephyr/prj.conf +++ b/src/samples/mini/zephyr/prj.conf @@ -1,4 +1,4 @@ -#Logging +# Logging CONFIG_LOG=y CONFIG_LOG_MODE_MINIMAL=y From 3dba5c6c7d000c156ecc0cd917797a03fd24fba7 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 11 Dec 2025 20:02:12 +0100 Subject: [PATCH 094/234] chore: remove spurious Signed-off-by: Marco Casaroli --- cmake/wamr.cmake | 7 --- src/samples/demo/posix/CMakeLists.txt | 1 - src/samples/supervisor/zephyr/shell.c | 6 --- src/shell/CMakeLists.txt | 10 ----- zephyr/wamr copy.cmake | 63 --------------------------- zephyr/wamr.cmake | 10 ----- 6 files changed, 97 deletions(-) delete mode 100644 zephyr/wamr copy.cmake diff --git a/cmake/wamr.cmake b/cmake/wamr.cmake index eef3adb9..c3b30739 100644 --- a/cmake/wamr.cmake +++ b/cmake/wamr.cmake @@ -14,13 +14,6 @@ if (NOT DEFINED WAMR_BUILD_PLATFORM) set (WAMR_BUILD_PLATFORM "linux") endif() -# if (NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_POOL) -# set (WAMR_BUILD_GLOBAL_HEAP_POOL 1) -# endif () -# if (NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_SIZE) -# set (WAMR_BUILD_GLOBAL_HEAP_SIZE 32767) -# endif () - # Set WAMR_BUILD_TARGET, currently values supported: # "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", # "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]" diff --git a/src/samples/demo/posix/CMakeLists.txt b/src/samples/demo/posix/CMakeLists.txt index 0cf4d426..ec37f85f 100644 --- a/src/samples/demo/posix/CMakeLists.txt +++ b/src/samples/demo/posix/CMakeLists.txt @@ -1,6 +1,5 @@ cmake_minimum_required(VERSION 3.20.0) - project (ocre_sample_demo) add_executable(ocre_demo diff --git a/src/samples/supervisor/zephyr/shell.c b/src/samples/supervisor/zephyr/shell.c index 5ac0686d..4c5ba327 100644 --- a/src/samples/supervisor/zephyr/shell.c +++ b/src/samples/supervisor/zephyr/shell.c @@ -10,12 +10,6 @@ extern struct ocre_context *ocre_global_context; static int cmd_ocre_shell(const struct shell *sh, size_t argc, char **argv) { - // getopt_init(); - - // volatile struct getopt_state *state = getopt_state_get(); - - // optreset = 1; - return ocre_shell(ocre_global_context, argc, argv); } diff --git a/src/shell/CMakeLists.txt b/src/shell/CMakeLists.txt index 9478ce9d..30203503 100644 --- a/src/shell/CMakeLists.txt +++ b/src/shell/CMakeLists.txt @@ -26,13 +26,3 @@ target_include_directories(OcreShell PUBLIC include ) - -# target_link_libraries(OcreShell -# PUBLIC -# zephyr_interface -# ) - -# target_link_libraries(ocre -# PRIVATE -# -lpthread -# ) diff --git a/zephyr/wamr copy.cmake b/zephyr/wamr copy.cmake deleted file mode 100644 index 0055656c..00000000 --- a/zephyr/wamr copy.cmake +++ /dev/null @@ -1,63 +0,0 @@ -# Determine the ISA of the target and set appropriately -if (DEFINED CONFIG_ISA_THUMB2) - set(TARGET_ISA THUMB) -elseif (DEFINED CONFIG_ISA_ARM) - set(TARGET_ISA ARM) -elseif (DEFINED CONFIG_X86) - set(TARGET_ISA X86_32) -elseif (DEFINED CONFIG_XTENSA) - set(TARGET_ISA XTENSA) -elseif (DEFINED CONFIG_RISCV) - set(TARGET_ISA RISCV32) -elseif (DEFINED CONFIG_ARCH_POSIX) - set(TARGET_ISA X86_32) -else () - message(FATAL_ERROR "Unsupported ISA: ${CONFIG_ARCH}") -endif () -message("TARGET ISA: ${TARGET_ISA}") - -add_compile_options(-O0 -Wno-unknown-attributes) - -# WAMR Options -set(WAMR_BUILD_PLATFORM "zephyr") -set(WAMR_BUILD_TARGET ${TARGET_ISA}) -set(WAMR_BUILD_INTERP 1) -set(WAMR_BUILD_FAST_INTERP 0) -set(WAMR_BUILD_AOT 0) -set(WAMR_BUILD_JIT 0) -set(WAMR_BUILD_LIBC_BUILTIN 1) -set(WAMR_BUILD_LIBC_WASI 1) -set(WAMR_BUILD_LIB_PTHREAD 1) -set(WAMR_BUILD_REF_TYPES 1) -set(WASM_ENABLE_LOG 1) - -# DEBUG -set(WAMR_BUILD_DEBUG_INTERP 1) - -if(NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_POOL) - set(WAMR_BUILD_GLOBAL_HEAP_POOL 1) -endif() -if(NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_SIZE) - set(WAMR_BUILD_GLOBAL_HEAP_SIZE 32767) -endif() - -enable_language (ASM) - -set (WAMR_BUILD_PLATFORM "zephyr") - -set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../wasm-micro-runtime) - -include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) - -# include(${WAMR_ROOT_DIR}/core/iwasm/libraries/lib-socket/lib_socket_wasi.cmake) - -add_library(vmlib) -target_sources(vmlib PRIVATE - ${WAMR_RUNTIME_LIB_SOURCE}) -target_link_libraries(vmlib zephyr_interface LITTLEFS) - -get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES) -target_include_directories(vmlib PUBLIC ${dirs}) - -get_property(defs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY COMPILE_DEFINITIONS) -target_compile_definitions(vmlib PRIVATE ${defs}) diff --git a/zephyr/wamr.cmake b/zephyr/wamr.cmake index 4bb1aafb..6090d682 100644 --- a/zephyr/wamr.cmake +++ b/zephyr/wamr.cmake @@ -31,16 +31,6 @@ set(WAMR_BUILD_REF_TYPES 1) set(WAMR_BUILD_SHARED_HEAP 1) set(WASM_ENABLE_LOG 1) -# DEBUG -#set(WAMR_BUILD_DEBUG_INTERP 1) - -# if(NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_POOL) -# set(WAMR_BUILD_GLOBAL_HEAP_POOL 1) -# endif() -# if(NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_SIZE) -# set(WAMR_BUILD_GLOBAL_HEAP_SIZE 32767) -# endif() - enable_language (ASM) set (WAMR_BUILD_PLATFORM "zephyr") From af008311aec605a2b561be677fc826bcc85e4c6f Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 11 Dec 2025 20:05:50 +0100 Subject: [PATCH 095/234] chore(zephyr/kconfig): cleanup unused log config We now honor the log level. Signed-off-by: Marco Casaroli --- zephyr/Kconfig | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 90e62e16..2e338082 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -201,30 +201,6 @@ config OCRE_SHELL comment "Logging" -config OCRE_LOG_DEBUG - bool "Debug logging" - default n - help - Enable Ocre debug logging - -config OCRE_LOG_ERR - bool "Error logging" - default y - help - Enable Ocre debug logging - -config OCRE_LOG_WARN - bool "Warn logging" - default y - help - Enable Ocre debug logging - -config OCRE_LOG_INF - bool "Info logging" - default y - help - Enable Ocre debug logging - module = OCRE module-str = OCRE source "subsys/logging/Kconfig.template.log_config" From 432319730d7020eca1f1415535dbedc203afb8d6 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 11 Dec 2025 20:36:11 +0100 Subject: [PATCH 096/234] fix(shell): handle getopt properly We use + in getopt to make sure gnu getopt will stop parsing when it encounters non option arguments. It looks like this does not hurt Zephyr. We also parse the -v in ocre shell command to print the context and set verbose mode, that can be used in the future. Signed-off-by: Marco Casaroli --- src/shell/container/create.c | 8 ++++--- src/shell/shell.c | 43 ++++++++++++++++++++++++++++++------ 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/shell/container/create.c b/src/shell/container/create.c index 039e7758..698853db 100644 --- a/src/shell/container/create.c +++ b/src/shell/container/create.c @@ -49,10 +49,8 @@ int cmd_container_create_run(struct ocre_context *ctx, char *argv0, int argc, ch size_t environment_count = 0; size_t mounts_count = 0; - opterr = 0; - int opt; - while ((opt = getopt(argc, argv, "de:k:n:r:v:")) != -1) { + while ((opt = getopt(argc, argv, "+de:k:n:r:v:")) != -1) { switch (opt) { case 'd': { if (detached) { @@ -134,6 +132,10 @@ int cmd_container_create_run(struct ocre_context *ctx, char *argv0, int argc, ch fprintf(stderr, "Invalid option '-%c'\n", optopt); goto cleanup; } + default: { + fprintf(stderr, "Invalid option '-%c'\n", optopt); + goto cleanup; + } } } diff --git a/src/shell/shell.c b/src/shell/shell.c index 47951cd9..8283f26b 100644 --- a/src/shell/shell.c +++ b/src/shell/shell.c @@ -1,6 +1,7 @@ #include #include #include +#include #include // for context // maybe for api? @@ -27,13 +28,17 @@ static int print_version(struct ocre_context *ctx, char *argv0, int argc, char * static int print_usage(struct ocre_context *ctx, char *argv0, int argc, char **argv) { - fprintf(stderr, "Usage: %s \n", argv0); + fprintf(stderr, "Usage: %s [-v] \n", argv0); + + fprintf(stderr, "\nOptions:\n"); + fprintf(stderr, " -v Verbose mode\n"); fprintf(stderr, "\nCommands:\n"); fprintf(stderr, " help Display this help message\n"); fprintf(stderr, " version Display version information\n"); fprintf(stderr, " image Image manipulation commands\n"); fprintf(stderr, " container Container management commands\n"); + fprintf(stderr, "\nShortcut Commands:\n"); fprintf(stderr, " ps container ps\n"); fprintf(stderr, " create container create\n"); @@ -72,21 +77,45 @@ static const struct ocre_command commands[] = { int ocre_shell(struct ocre_context *ctx, int argc, char *argv[]) { - if (argc < 2) { + int opt; + bool verbose = false; + while ((opt = getopt(argc, argv, "+v")) != -1) { + switch (opt) { + case 'v': { + if (verbose) { + fprintf(stderr, "'-v' can be set only once\n\n"); + print_usage(ctx, argv[0], argc, argv); + return -1; + } + + verbose = true; + continue; + } + case '?': { + fprintf(stderr, "Invalid option: '%c'\n", optopt); + return -1; + } + } + } + + if (argc <= optind) { return print_usage(ctx, argv[0], argc, argv); } - fprintf(stderr, "Using context: %p\n", ctx); + if (verbose) { + fprintf(stderr, "Using context: %p\n", ctx); + } - optind = 1; + int save_optind = optind; for (size_t i = 0; i < sizeof(commands) / sizeof(commands[0]); i++) { - if (!strcmp(argv[1], commands[i].name)) { - return commands[i].func(ctx, argv[0], argc - 1, &argv[1]); + if (argv[save_optind] && !strcmp(argv[save_optind], commands[i].name)) { + optind = 1; + return commands[i].func(ctx, argv[0], argc - save_optind, &argv[save_optind]); } } - fprintf(stderr, "Invalid command: '%s %s'\n\n", argv[0], argv[1]); + fprintf(stderr, "Invalid command: '%s %s'\n\n", argv[0], argv[save_optind]); return print_usage(ctx, argv[0], argc, argv); From ef23001a8fcbb387da4c354fb4eb30d5899e52bd Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 11 Dec 2025 20:52:34 +0100 Subject: [PATCH 097/234] feat(shell/container): outputs These will output the container id on success. container wait will output the return status code. Signed-off-by: Marco Casaroli --- src/shell/container/create.c | 2 ++ src/shell/container/kill.c | 6 +++++- src/shell/container/pause.c | 7 +++++-- src/shell/container/rm.c | 6 +++++- src/shell/container/start.c | 6 +++++- src/shell/container/stop.c | 6 +++++- src/shell/container/unpause.c | 7 +++++-- src/shell/container/wait.c | 4 +++- 8 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/shell/container/create.c b/src/shell/container/create.c index 698853db..55e955a5 100644 --- a/src/shell/container/create.c +++ b/src/shell/container/create.c @@ -178,7 +178,9 @@ int cmd_container_create_run(struct ocre_context *ctx, char *argv0, int argc, ch if (detached) { char *cid = ocre_container_get_id_a(container); + fprintf(stdout, "%s\n", cid); + free(cid); } diff --git a/src/shell/container/kill.c b/src/shell/container/kill.c index 602b6922..6df63087 100644 --- a/src/shell/container/kill.c +++ b/src/shell/container/kill.c @@ -26,7 +26,11 @@ int cmd_container_kill(struct ocre_context *ctx, char *argv0, int argc, char **a return -1; } - return ocre_container_kill(container); + int rc = ocre_container_kill(container); + + fprintf(stdout, "%s\n", argv[1]); + + return rc; } else { fprintf(stderr, "'%s container kill' requires exactly one argument\n\n", argv0); return usage(argv0); diff --git a/src/shell/container/pause.c b/src/shell/container/pause.c index 7a47bd3a..a14a9aa7 100644 --- a/src/shell/container/pause.c +++ b/src/shell/container/pause.c @@ -15,7 +15,6 @@ static int usage(const char *argv0) int cmd_container_pause(struct ocre_context *ctx, char *argv0, int argc, char **argv) { if (argc == 2) { - struct ocre_container *container = ocre_context_get_container_by_id(ctx, argv[1]); if (!container) { fprintf(stderr, "Failed to get container '%s'\n", argv[1]); @@ -27,7 +26,11 @@ int cmd_container_pause(struct ocre_context *ctx, char *argv0, int argc, char ** return -1; } - return ocre_container_pause(container); + int rc = ocre_container_pause(container); + + fprintf(stdout, "%s\n", argv[1]); + + return rc; } else { fprintf(stderr, "'%s container pause' requires exactly one argument\n\n", argv0); return usage(argv0); diff --git a/src/shell/container/rm.c b/src/shell/container/rm.c index 8d939c93..2bcc01db 100644 --- a/src/shell/container/rm.c +++ b/src/shell/container/rm.c @@ -27,7 +27,11 @@ int cmd_container_rm(struct ocre_context *ctx, char *argv0, int argc, char **arg return -1; } - return ocre_context_remove_container(ctx, container); + int rc = ocre_context_remove_container(ctx, container); + + fprintf(stdout, "%s\n", argv[1]); + + return rc; } else { fprintf(stderr, "'%s container rm' requires exactly one argument\n\n", argv0); return usage(argv0); diff --git a/src/shell/container/start.c b/src/shell/container/start.c index 6e3cdd99..02299b42 100644 --- a/src/shell/container/start.c +++ b/src/shell/container/start.c @@ -27,7 +27,11 @@ int cmd_container_start(struct ocre_context *ctx, char *argv0, int argc, char ** return -1; } - return ocre_container_start(container); + int rc = ocre_container_start(container); + + fprintf(stdout, "%s\n", argv[1]); + + return rc; } else { fprintf(stderr, "'%s container start' requires exactly one argument\n\n", argv0); return usage(argv0); diff --git a/src/shell/container/stop.c b/src/shell/container/stop.c index 6b87c970..f4d5c665 100644 --- a/src/shell/container/stop.c +++ b/src/shell/container/stop.c @@ -26,7 +26,11 @@ int cmd_container_stop(struct ocre_context *ctx, char *argv0, int argc, char **a return -1; } - return ocre_container_stop(container); + int rc = ocre_container_stop(container); + + fprintf(stdout, "%s\n", argv[1]); + + return rc; } else { fprintf(stderr, "'%s container stop' requires exactly one argument\n\n", argv0); return usage(argv0); diff --git a/src/shell/container/unpause.c b/src/shell/container/unpause.c index 1acdaa57..1381c07c 100644 --- a/src/shell/container/unpause.c +++ b/src/shell/container/unpause.c @@ -15,7 +15,6 @@ static int usage(const char *argv0) int cmd_container_unpause(struct ocre_context *ctx, char *argv0, int argc, char **argv) { if (argc == 2) { - struct ocre_container *container = ocre_context_get_container_by_id(ctx, argv[1]); if (!container) { fprintf(stderr, "Failed to get container '%s'\n", argv[1]); @@ -27,7 +26,11 @@ int cmd_container_unpause(struct ocre_context *ctx, char *argv0, int argc, char return -1; } - return ocre_container_unpause(container); + int rc = ocre_container_unpause(container); + + fprintf(stdout, "%s\n", argv[1]); + + return rc; } else { fprintf(stderr, "'%s container unpause' requires exactly one argument\n\n", argv0); return usage(argv0); diff --git a/src/shell/container/wait.c b/src/shell/container/wait.c index dba65cc4..90455878 100644 --- a/src/shell/container/wait.c +++ b/src/shell/container/wait.c @@ -34,7 +34,9 @@ int cmd_container_wait(struct ocre_context *ctx, char *argv0, int argc, char **a return -1; } - return return_code; + fprintf(stdout, "%d\n", return_code); + + return rc; } else { fprintf(stderr, "'%s container wait' requires exactly one argument\n\n", argv0); return usage(argv0); From 6a4292516043841dd960490d81f9d1f76dd96c06 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 11 Dec 2025 20:53:19 +0100 Subject: [PATCH 098/234] fix(container): typo Signed-off-by: Marco Casaroli --- src/ocre/container.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ocre/container.c b/src/ocre/container.c index fcc57a7e..bd282464 100644 --- a/src/ocre/container.c +++ b/src/ocre/container.c @@ -617,7 +617,7 @@ int ocre_container_wait(struct ocre_container *container, int *status) if (container->status == OCRE_CONTAINER_STATUS_EXITED) { LOG_INF("Container '%s' was exited", container->id); if (ocre_container_status_locked(container) != OCRE_CONTAINER_STATUS_STOPPED) { - LOG_ERR("Container '%s' status did not go drom exitted to stopped", container->id); + LOG_ERR("Container '%s' status did not go from exited to stopped", container->id); goto unlock_mutex; } } From 06b015af660e62acaff71ab388c3f5106dda4c37 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 11 Dec 2025 22:23:36 +0100 Subject: [PATCH 099/234] feat(supervisor): use startup function So the user can have their own main() Signed-off-by: Marco Casaroli --- src/samples/supervisor/zephyr/service.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/samples/supervisor/zephyr/service.c b/src/samples/supervisor/zephyr/service.c index eb2b7705..ebfe622e 100644 --- a/src/samples/supervisor/zephyr/service.c +++ b/src/samples/supervisor/zephyr/service.c @@ -1,10 +1,12 @@ #include #include +#include + // keep a reference to the single instance of the runtime struct ocre_context *ocre_global_context = NULL; -int main(int argc, char *argv[]) +static int ocre_service_init() { // Initialize OCRE if (ocre_initialize() != 0) { @@ -25,3 +27,5 @@ int main(int argc, char *argv[]) return 0; } + +SYS_INIT(ocre_service_init, APPLICATION, 0); From a21a2dbbec9b9e5a6460ac745079c6953d5fa953 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Fri, 12 Dec 2025 10:58:28 +0100 Subject: [PATCH 100/234] feat(samples/mini): handle sample file In the mini configuration, sometimes we will not be able to write the state_information partition, so we just embed the file in the binary and it will create it if it is non-existent. The user can also override the image using the cmake variable OCRE_INPUT_FILE. We also ditch xxd and instead use a more portable solution using awk, because xxd in Ubuntu 22.04 LTS does not support option -n. Signed-off-by: Marco Casaroli --- cmake/input_file.cmake | 19 -------- scripts/c_array.awk | 18 +++++++ src/samples/mini/hello-world.wasm | Bin 0 -> 3126 bytes src/samples/mini/input_file.cmake | 24 ++++++++++ src/samples/mini/main.c | 64 ++++++++++++++++++++++++- src/samples/mini/posix/CMakeLists.txt | 3 ++ src/samples/mini/zephyr/CMakeLists.txt | 3 ++ 7 files changed, 111 insertions(+), 20 deletions(-) delete mode 100644 cmake/input_file.cmake create mode 100644 scripts/c_array.awk create mode 100755 src/samples/mini/hello-world.wasm create mode 100644 src/samples/mini/input_file.cmake diff --git a/cmake/input_file.cmake b/cmake/input_file.cmake deleted file mode 100644 index 2cd9fdd6..00000000 --- a/cmake/input_file.cmake +++ /dev/null @@ -1,19 +0,0 @@ -if(NOT "${OCRE_INPUT_FILE}" STREQUAL "") - message("Using input file: ${OCRE_INPUT_FILE}") - - # Extract filename without extension for use in software - get_filename_component(OCRE_INPUT_FILE_NAME ${OCRE_INPUT_FILE} NAME_WE) - message("Input file name (without extension): ${OCRE_INPUT_FILE_NAME}") - add_definitions(-DOCRE_INPUT_FILE_NAME="${OCRE_INPUT_FILE_NAME}") - - add_custom_command( - OUTPUT ${CMAKE_CURRENT_LIST_DIR}/src/ocre/ocre_input_file.g - COMMAND xxd -n wasm_binary -i ${OCRE_INPUT_FILE} | sed 's/^unsigned/static const unsigned/' > ${OCRE_ROOT_DIR}/src/ocre/ocre_input_file.g - DEPENDS ${OCRE_INPUT_FILE} - COMMENT "Generating C header from ${OCRE_INPUT_FILE}" - ) - - add_definitions(-DHAS_GENERATED_INPUT) - - add_custom_target(generate_ocre_file DEPENDS ${CMAKE_CURRENT_LIST_DIR}/src/ocre/ocre_input_file.g) -endif() diff --git a/scripts/c_array.awk b/scripts/c_array.awk new file mode 100644 index 00000000..f9ca0ceb --- /dev/null +++ b/scripts/c_array.awk @@ -0,0 +1,18 @@ +BEGIN { + printf "/* Auto-generated file. DO NOT EDIT! */\n\n" + printf "#include \n\n" + printf "const unsigned char ocre_mini_sample_image[] = {\n " + count = 0 +} +{ + for(i=1; i<=NF; i++) { + if(count > 0) printf ", " + if(count % 12 == 0 && count > 0) printf "\n " + printf "0x%s", $i + count++ + } +} +END { + printf "\n};\n\n" + printf "const size_t ocre_mini_sample_image_len = %d;\n", count +} diff --git a/src/samples/mini/hello-world.wasm b/src/samples/mini/hello-world.wasm new file mode 100755 index 0000000000000000000000000000000000000000..818f466e217916f1b4895d22a94ee8d3820b732e GIT binary patch literal 3126 zcmcguOOG2x5UzgAclcIyr1DAK!^hu4j@J11{`ugh(jbeaNx)fK?+~>jMoccMJ_P*baz!(*Ym5kX?b{B z5RtgQeq0qrAqq_A3vvFq;I;G|4GvQp0z8X?juXD3kXJ--$L8{IwKqJoygqz(ZPZ&I z^q*htZ{8c7Tg$8G6TSY~)e(hi?|iKmNu`4jb4>Em;Wn`(Mb&T1fq!#^! z<3vYN{1VH=FY}mC{1(raTB2>pSc>0Zn#?Y8lUG>o1E%-Dmo}tg5YT`9y4rw*B`f06 zqUYT1IaXQ~U!2KpN)NY4 zAyNx!HxF}1T2STiVao1;;Dr3J$CP3^6}%Ot(u-PQW&V}(yoFuf{Yspr?n{w0gOd)# zPway?d6NcN!%dqjZCv>uZ2Y%zm}5Yn_31y93Rh%S3_9{qnKA+=+Cb4DAe_YpxuOlA z9i|7QE>A6{z~vkZbhxG{5Yl*0){!w__q7y30ZfTgiDrmfwJ75>XrbUq2&BEs^==8z zP695uwgFSS(^~#G>?&x~%-D{NBy0);4Ut!=A*Pd{WCf)S0N{x&Hmk^zPh2=!5X?0>r6m5zJ7TV)*2WL^UO9hs{K>3s~(=kzC(ci(m+MU2LQ! zZM75LWzBjC+2s@Px1GTs9Nk_JC!oU{5XQ;_)P@0w##!Z?GN-&V?&@oZA->F!_zE$a z%1)YaCvi=%u_%9KxzsOz;iYGDCg76a!@2>t9JNiU)HUMwz1q8;<16WIia%tMosMx8 zvNl!?akA8r*SxvHpad}YVEhq_m<=JfWmc8mBQEXJih?}KI^5ps{4^? z1T@R|WA6e3TV`p{h1u{3gOl%;iB#}Tk=2sE0{(;5ncHgipMR<;0GPbF^KD{f!bzMZPneUla@jl;Wx2|9AlfL4U)?JF!35qOpvXz?I;>*1uz@m( zM3xta+=dH-({_qoX%50O=YMKC(jt+>x5rh&aUV|nDO+K}6&=~-KmdsN6Xu!~bo8uO zD@09QM2n!|5EEPl%D157e&oKF?iwALuRwITKq)x>{VKX45By`!^=Gr6d9y$B9bqXE zr75TQ60clmPc7wqjiaA%!~0Fn34Wdhm;la=O!ZGpT{2s6Ot^8D;0|&xWQkB+EO6%v zH@SEzLL?BB{0BhgRt? input_file.hex + DEPENDS ${OCRE_INPUT_FILE} + COMMENT "Generating hex file from ${OCRE_INPUT_FILE}" +) + +add_custom_command( + OUTPUT input_file.c + COMMAND awk -f "${CMAKE_CURRENT_LIST_DIR}/../../../scripts/c_array.awk" input_file.hex > input_file.c + DEPENDS + input_file.hex + ${CMAKE_CURRENT_LIST_DIR}/../../../scripts/c_array.awk + COMMENT "Generating C array" +) + +add_custom_target(input_file DEPENDS input_file.c) diff --git a/src/samples/mini/main.c b/src/samples/mini/main.c index b129ad36..599d6466 100644 --- a/src/samples/mini/main.c +++ b/src/samples/mini/main.c @@ -1,8 +1,35 @@ #include #include +#include +#include +#include +#include +#include #include +extern const unsigned char ocre_mini_sample_image[]; +extern const size_t ocre_mini_sample_image_len; + +static int create_sample_file(char *path) +{ + int fd = open(path, O_CREAT | O_WRONLY, 0644); + if (fd == -1) { + perror("Failed to create sample file"); + return -1; + } + + ssize_t bytes_written = write(fd, ocre_mini_sample_image, ocre_mini_sample_image_len); + if (bytes_written != ocre_mini_sample_image_len) { + perror("Failed to write to sample file"); + close(fd); + return -1; + } + + close(fd); + return 0; +} + int main(int argc, char *argv[]) { int rc; @@ -19,8 +46,43 @@ int main(int argc, char *argv[]) return 1; } + char *workdir = ocre_context_get_working_directory(ocre); + if (!workdir) { + fprintf(stderr, "Failed to get working directory\n"); + return 1; + } + + char *sample_path = malloc(strlen(workdir) + strlen("/images/sample.wasm") + 1); + if (!sample_path) { + fprintf(stderr, "Failed to allocate memory for sample path\n"); + return 1; + } + sprintf(sample_path, "%s/images/sample.wasm", workdir); + + struct stat st; + + if (stat(sample_path, &st) == -1) { + if (errno == ENOENT) { + fprintf(stderr, "Creating sample file '%s'\n", sample_path); + if (create_sample_file(sample_path)) { + fprintf(stderr, "Failed to create sample file\n"); + free(sample_path); + return 1; + } + } else { + perror("Failed to stat sample file"); + free(sample_path); + return 1; + } + } + else { + fprintf(stderr, "Sample file '%s' already exists\n", sample_path); + } + + free(sample_path); + struct ocre_container *container = - ocre_context_create_container(ocre, "hello-world.wasm", "wamr", NULL, false, NULL); + ocre_context_create_container(ocre, "sample.wasm", "wamr", NULL, false, NULL); if (!container) { fprintf(stderr, "Failed to create container\n"); diff --git a/src/samples/mini/posix/CMakeLists.txt b/src/samples/mini/posix/CMakeLists.txt index 6b53d72e..a9934829 100644 --- a/src/samples/mini/posix/CMakeLists.txt +++ b/src/samples/mini/posix/CMakeLists.txt @@ -2,8 +2,11 @@ cmake_minimum_required(VERSION 3.20.0) project (ocre_sample_mini) +include(../input_file.cmake) + add_executable(ocre_mini ../main.c + input_file.c ) target_link_libraries(ocre_mini diff --git a/src/samples/mini/zephyr/CMakeLists.txt b/src/samples/mini/zephyr/CMakeLists.txt index 507015f8..17efe0f7 100644 --- a/src/samples/mini/zephyr/CMakeLists.txt +++ b/src/samples/mini/zephyr/CMakeLists.txt @@ -10,9 +10,12 @@ find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project (ocre_sample_mini) +include(../input_file.cmake) + target_sources(app PRIVATE ../main.c + input_file.c ) target_link_libraries(app From d2b38122a3489885d1fd36bc1ccfec22e7dd7fc1 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Fri, 12 Dec 2025 17:09:15 +0100 Subject: [PATCH 101/234] fix: honor FILESYSTEM and NETWORKING config options If these are not enable, we will not include their respective code. Signed-off-by: Marco Casaroli --- src/ocre/context.c | 8 ++++++++ src/runtime/wamr/wamr.c | 41 +++++++++++++++++++++++++++-------------- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/src/ocre/context.c b/src/ocre/context.c index ac2bc97e..73141e74 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -33,6 +33,7 @@ struct container_node { struct container_node *next; /* needed for singly- or doubly-linked lists */ }; +#if CONFIG_OCRE_FILESYSTEM static int delete_container_workdirs(const char *working_directory) { int ret = -1; @@ -89,6 +90,7 @@ static int delete_container_workdirs(const char *working_directory) return ret; } +#endif struct ocre_context *ocre_create_context(const char *workdir) { @@ -116,7 +118,9 @@ struct ocre_context *ocre_create_context(const char *workdir) goto error; } +#if CONFIG_OCRE_FILESYSTEM delete_container_workdirs(context->working_directory); +#endif rc = pthread_mutex_init(&context->mutex, NULL); if (rc) { @@ -262,6 +266,7 @@ struct ocre_container *ocre_context_create_container(struct ocre_context *contex /* Build the path to the working dir and create it */ +#if CONFIG_OCRE_FILESYSTEM if (arguments && string_array_lookup(arguments->capabilities, "filesystem")) { container_workdir = malloc(strlen(context->working_directory) + strlen("/containers/") + strlen(computed_container_id) + 1); @@ -281,6 +286,7 @@ struct ocre_container *ocre_context_create_container(struct ocre_context *contex goto error; } } +#endif /* Create the container */ @@ -344,6 +350,7 @@ int ocre_context_remove_container(struct ocre_context *context, struct ocre_cont return rc; } +#if CONFIG_OCRE_FILESYSTEM if (node->working_directory) { rc = rm_rf(node->working_directory); if (rc) { @@ -351,6 +358,7 @@ int ocre_context_remove_container(struct ocre_context *context, struct ocre_cont node->working_directory, rc); } } +#endif LL_DELETE(context->containers, node); diff --git a/src/runtime/wamr/wamr.c b/src/runtime/wamr/wamr.c index 8f8a69d1..b4b8fbe4 100644 --- a/src/runtime/wamr/wamr.c +++ b/src/runtime/wamr/wamr.c @@ -257,7 +257,10 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s /* Process capabilities */ for (const char **cap = capabilities; cap && *cap; cap++) { - if (!strcmp(*cap, "networking")) { + if (0) { + } +#if CONFIG_OCRE_NETWORKING + else if (!strcmp(*cap, "networking")) { const char *addr_pool[] = { "0.0.0.0/0", }; @@ -271,7 +274,10 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s sizeof(ns_lookup_pool) / sizeof(ns_lookup_pool[0])); LOG_INF("Network capability enabled"); - } else if (!strcmp(*cap, "filesystem") && workdir) { + } +#endif +#if CONFIG_OCRE_FILESYSTEM + else if (!strcmp(*cap, "filesystem") && workdir) { dir_map_list = malloc(sizeof(char *)); if (!dir_map_list) { LOG_ERR("Failed to allocate memory for dir_map_list"); @@ -293,12 +299,12 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s LOG_INF("Filesystem capability enabled"); } +#endif } /* Add the mounts to the directory map list */ for (const char **mount = mounts; mount && *mount; mount++) { - /* Need to insert the extra ':' */ dir_map_list[dir_map_list_len] = malloc(strlen(*mount) + 2); @@ -321,16 +327,15 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s goto error; } - sprintf(dst_colon+1, ":%s", src_colon+1); + sprintf(dst_colon + 1, ":%s", src_colon + 1); LOG_INF("Enabled mount: %s", dir_map_list[dir_map_list_len]); dir_map_list_len++; - } - wasm_runtime_set_wasi_args(context->module, NULL, 0, (const char **)dir_map_list, dir_map_list_len, envp, envn, context->argv, - argc + 1); + wasm_runtime_set_wasi_args(context->module, NULL, 0, (const char **)dir_map_list, dir_map_list_len, envp, envn, + context->argv, argc + 1); context->module_inst = wasm_runtime_instantiate(context->module, stack_size, heap_size, context->error_buf, sizeof(context->error_buf)); @@ -340,9 +345,19 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s } for (const char **cap = capabilities; cap && *cap; cap++) { - if (!strcmp(*cap, "networking") || !strcmp(*cap, "filesystem")) { + if (0) { + } +#if CONFIG_OCRE_NETWORKING + else if (!strcmp(*cap, "networking")) { // already set up - } else if (!strcmp(*cap, "ocre:api")) { + } +#endif +#if CONFIG_OCRE_FILESYSTEM + else if (!strcmp(*cap, "filesystem")) { + // already set up + } +#endif + else if (!strcmp(*cap, "ocre:api")) { context->uses_ocre_api = true; ocre_module_context_t *mod = ocre_register_module(context->module_inst); wasm_runtime_set_custom_data(context->module_inst, mod); @@ -370,12 +385,10 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s context->buffer = NULL; error_argv: - free(context->argv[0]); free(context->argv); error: - for (char **dir_map = dir_map_list; dir_map && *dir_map; dir_map++) { free(*dir_map); } @@ -497,7 +510,7 @@ const struct ocre_runtime_vtable wamr_vtable = { .destroy = instance_destroy, .thread_execute = instance_thread_execute, .kill = instance_kill, - .stop = instance_stop, - .pause = instance_pause, - .unpause = instance_unpause, + // .stop = instance_stop, + // .pause = instance_pause, + // .unpause = instance_unpause, }; From 083de6fb6b4a9fbc3729502c85625fb4d96f7ce7 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 15 Dec 2025 14:35:12 +0100 Subject: [PATCH 102/234] feat(context): create working directory structure on startup If we have not flashed the storage_partition data, the directories will not exist. We create them empty if they are not found. Signed-off-by: Marco Casaroli --- src/ocre/context.c | 80 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/src/ocre/context.c b/src/ocre/context.c index 73141e74..69a755a4 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -92,6 +92,76 @@ static int delete_container_workdirs(const char *working_directory) } #endif +static int create_dir_if_not_exists(const char *path) +{ + int rc; + struct stat st; + + rc = stat(path, &st); + if (rc && errno == ENOENT) { + LOG_INF("Directory '%s' does not exist, creating...", path); + rc = mkdir(path, 0755); + if (rc) { + LOG_ERR("Failed to create directory '%s': errno=%d", path, errno); + return -1; + } + } else if (!rc && !S_ISDIR(st.st_mode)) { + LOG_ERR("Path '%s' is not a directory", path); + return -1; + } else if (!rc && S_ISDIR(st.st_mode)) { + LOG_INF("Directory '%s' already exists", path); + } + + return 0; +} + +static int populate_ocre_workdir(const char *working_directory) +{ + int rc = -1; + char *containers_path = NULL; + char *images_path = NULL; + + rc = create_dir_if_not_exists(working_directory); + if (rc) { + LOG_ERR("Failed to create OCRE working directory '%s': errno=%d", working_directory, errno); + return -1; + } + + containers_path = malloc(strlen(working_directory) + strlen("/containers") + 1); + if (!containers_path) { + LOG_ERR("Failed to allocate memory for container workdir path"); + goto finish; + } + + sprintf(containers_path, "%s/containers", working_directory); + + rc = create_dir_if_not_exists(containers_path); + if (rc) { + LOG_ERR("Failed to create Ocre containers directory '%s': errno=%d", containers_path, errno); + goto finish; + } + + images_path = malloc(strlen(working_directory) + strlen("/images") + 1); + if (!images_path) { + LOG_ERR("Failed to allocate memory for container workdir path"); + goto finish; + } + + sprintf(images_path, "%s/images", working_directory); + + rc = create_dir_if_not_exists(images_path); + if (rc) { + LOG_ERR("Failed to create OCRE images directory '%s': errno=%d", images_path, errno); + goto finish; + } + +finish: + free(containers_path); + free(images_path); + + return rc; +} + struct ocre_context *ocre_create_context(const char *workdir) { int rc; @@ -109,8 +179,6 @@ struct ocre_context *ocre_create_context(const char *workdir) memset(context, 0, sizeof(struct ocre_context)); - /* Initialize working directory */ - context->working_directory = strdup(workdir); if (!context->working_directory) { LOG_ERR("Failed to allocate memory for working directory: errno=%d", errno); @@ -118,6 +186,14 @@ struct ocre_context *ocre_create_context(const char *workdir) goto error; } + /* Initialize working directory */ + + rc = populate_ocre_workdir(context->working_directory); + if (rc) { + LOG_ERR("Failed to populate OCRE working directory: rc=%d", rc); + goto error; + } + #if CONFIG_OCRE_FILESYSTEM delete_container_workdirs(context->working_directory); #endif From 228376a9126dc93204da5811aa6237583947e24f Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 15 Dec 2025 14:36:34 +0100 Subject: [PATCH 103/234] feat(supervisor/zephyr): download file functionality We will need this for ocre image pull command Signed-off-by: Marco Casaroli --- src/samples/supervisor/zephyr/CMakeLists.txt | 1 + src/samples/supervisor/zephyr/download_file.c | 197 ++++++++++++++++++ 2 files changed, 198 insertions(+) create mode 100644 src/samples/supervisor/zephyr/download_file.c diff --git a/src/samples/supervisor/zephyr/CMakeLists.txt b/src/samples/supervisor/zephyr/CMakeLists.txt index b1d647ee..dd77b616 100644 --- a/src/samples/supervisor/zephyr/CMakeLists.txt +++ b/src/samples/supervisor/zephyr/CMakeLists.txt @@ -14,6 +14,7 @@ target_sources(app PRIVATE service.c shell.c + download_file.c ) target_link_libraries(app diff --git a/src/samples/supervisor/zephyr/download_file.c b/src/samples/supervisor/zephyr/download_file.c new file mode 100644 index 00000000..9878f0c9 --- /dev/null +++ b/src/samples/supervisor/zephyr/download_file.c @@ -0,0 +1,197 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define OCRE_DOWNLOAD_RESPONSE_BUFFER_SIZE (256) + +static int response_cb(struct http_response *rsp, enum http_final_call final_data, void *user_data) +{ + int fd = *(int *)user_data; + + if (rsp->http_status_code != HTTP_200_OK) { + fprintf(stderr, "Got invalid HTTP status code %d\n", rsp->http_status_code); + return -1; + } + + if (rsp->body_frag_start && rsp->body_frag_len) { + size_t body_frag_len = rsp->data_len - (rsp->body_frag_start - rsp->recv_buf); + + int rc = write(fd, rsp->body_frag_start, body_frag_len); + if (rc < 0) { + fprintf(stderr, "Failed to write file: %d\n", rc); + return -1; + } + } + + return 0; +} + +int ocre_download_file(const char *url, const char *filepath) +{ + int rc = -1; + char *hostname = NULL; + struct addrinfo *res = NULL; + char *response = NULL; + + /* Parse URL */ + + struct http_parser_url parsed_url; + http_parser_url_init(&parsed_url); + http_parser_parse_url(url, strlen(url), 0, &parsed_url); + + if (!(parsed_url.field_set & (1 << UF_SCHEMA))) { + fprintf(stderr, "Missing URL schema. Use 'http:// in URL\n"); + goto finish; + } + + if (!(parsed_url.field_set & (1 << UF_PATH))) { + fprintf(stderr, "Missing URL path. Use 'http:/// in URL\n"); + goto finish; + } + + uint16_t port = 0; + char port_str[6]; + + if (!strncmp("http", url + parsed_url.field_data[UF_SCHEMA].off, parsed_url.field_data[UF_SCHEMA].len)) { + port = 80; + strcpy(port_str, "80"); + // } else if (!strncmp("https", url + parsed_url.field_data[UF_SCHEMA].off, + // parsed_url.field_data[UF_SCHEMA].len)) { + // port = 443; + // strcpy(port_str, "443"); + } else { + fprintf(stderr, "Unsupported URL schema: '%s'", url + parsed_url.field_data[UF_SCHEMA].off); + goto finish; + } + + if (parsed_url.field_set & (1 << UF_PORT)) { + port = parsed_url.port; + memcpy(port_str, url + parsed_url.field_data[UF_PORT].off, parsed_url.field_data[UF_PORT].len); + port_str[parsed_url.field_data[UF_PORT].len] = '\0'; + } + + if (!(parsed_url.field_set & (1 << UF_HOST))) { + fprintf(stderr, "Missing URL host. Use 'http:// in URL\n"); + goto finish; + } + + response = malloc(OCRE_DOWNLOAD_RESPONSE_BUFFER_SIZE); + if (!response) { + fprintf(stderr, "Failed to allocate memory for response buffer\n"); + goto finish; + } + + /* Resolve hostname */ + + hostname = malloc(parsed_url.field_data[UF_HOST].len + 1); + if (!hostname) { + fprintf(stderr, "Failed to allocate memory for hostname"); + goto finish; + } + + memcpy(hostname, url + parsed_url.field_data[UF_HOST].off, parsed_url.field_data[UF_HOST].len); + hostname[parsed_url.field_data[UF_HOST].len] = '\0'; + + static struct addrinfo hints; + int st; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + st = getaddrinfo(hostname, port_str, &hints, &res); + + printf("getaddrinfo status: %d\n", st); + + if (st != 0) { + fprintf(stderr, "Unable to resolve address: %s\n", hostname); + goto finish; + } + + /* Create file */ + + int fd = open(filepath, O_CREAT | O_WRONLY, 0644); + if (fd < 0) { + fprintf(stderr, "Failed to create file '%s'\n", filepath); + goto finish; + } + + fprintf(stderr, "created file %s\n", filepath); + + /* Socket */ + + int sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + if (sock < 0) { + fprintf(stderr, "Error %d on socket()\n", sock); + goto finish; + } + + /* Connection */ + + st = connect(sock, res->ai_addr, res->ai_addrlen); + if (st < 0) { + fprintf(stderr, "Error %d on connect(), errno: %d\n", st, errno); + goto finish; + } + + /* HTTP Request */ + + struct http_request req; + + int32_t timeout = 3 * MSEC_PER_SEC; + + memset(&req, 0, sizeof(req)); + + req.method = HTTP_GET; + req.url = url + parsed_url.field_data[UF_PATH].off; + req.host = hostname; + req.protocol = "HTTP/1.1"; + req.response = response_cb; + req.recv_buf = response; + req.recv_buf_len = OCRE_DOWNLOAD_RESPONSE_BUFFER_SIZE; + + st = http_client_req(sock, &req, timeout, (void *)&fd); + fprintf(stderr, "st is %d\n", st); + if (st < 0) { + fprintf(stderr, "HTTP Client error %d\n", st); + goto finish; + } else { + fprintf(stderr, "finished downloading file!!!!\n"); + } + + rc = 0; + +finish: + + if (fd >= 0) { + close(fd); + } + + if (sock >= 0) { + close(sock); + } + + if (rc) { + unlink(filepath); + } + + if (res) { + freeaddrinfo(res); + } + + free(hostname); + + free(response); + + return rc; +} From b9d05994127cba6f1f066627b8a83e8cfaad1f23 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 15 Dec 2025 14:36:58 +0100 Subject: [PATCH 104/234] fix(shell/image/ls): additional error checks Signed-off-by: Marco Casaroli --- src/shell/image/ls.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/shell/image/ls.c b/src/shell/image/ls.c index 6c70f4f3..86af2678 100644 --- a/src/shell/image/ls.c +++ b/src/shell/image/ls.c @@ -88,13 +88,17 @@ static void header() static int list_image(const char *name, const char *path) { + struct stat st; + if (!path) { fprintf(stderr, "Invalid image path\n"); return -1; } - struct stat st; - stat(path, &st); + if (stat(path, &st)) { + fprintf(stderr, "Failed to stat image '%s'\n", path); + return -1; + } if (S_ISREG(st.st_mode)) { char hash[65] = {0}; /* hash[64] is null-byte */ From 6f6958a3dab77f7cd8f24fd84871166eca17253d Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 15 Dec 2025 14:37:29 +0100 Subject: [PATCH 105/234] fix(kconfig): enable HTTP and DNS client for shell We need these for ocre image pull Signed-off-by: Marco Casaroli --- zephyr/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 2e338082..113e3b70 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -195,6 +195,8 @@ config OCRE_SHELL bool "Enable OCRE Shell" select SHELL select SHELL_GETOPT + select HTTP_CLIENT + select DNS_RESOLVER default n help Enable the OCRE Shell for dynamic configuration management. From 922dc2df2c8bb8d6fed99e04876a7711db8438ea Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 15 Dec 2025 14:54:22 +0100 Subject: [PATCH 106/234] fix(download_file): initialize variables sock and fd Initialize to -1 so we can safely clean it up Signed-off-by: Marco Casaroli --- src/samples/supervisor/zephyr/download_file.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/samples/supervisor/zephyr/download_file.c b/src/samples/supervisor/zephyr/download_file.c index 9878f0c9..bc947f59 100644 --- a/src/samples/supervisor/zephyr/download_file.c +++ b/src/samples/supervisor/zephyr/download_file.c @@ -39,6 +39,8 @@ static int response_cb(struct http_response *rsp, enum http_final_call final_dat int ocre_download_file(const char *url, const char *filepath) { int rc = -1; + int fd = -1; + int sock = -1; char *hostname = NULL; struct addrinfo *res = NULL; char *response = NULL; @@ -119,7 +121,7 @@ int ocre_download_file(const char *url, const char *filepath) /* Create file */ - int fd = open(filepath, O_CREAT | O_WRONLY, 0644); + fd = open(filepath, O_CREAT | O_WRONLY, 0644); if (fd < 0) { fprintf(stderr, "Failed to create file '%s'\n", filepath); goto finish; @@ -129,7 +131,7 @@ int ocre_download_file(const char *url, const char *filepath) /* Socket */ - int sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (sock < 0) { fprintf(stderr, "Error %d on socket()\n", sock); From 4f41e7cf195b3e79facaff7bfd2dba5cfbb597ac Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 15 Dec 2025 14:55:16 +0100 Subject: [PATCH 107/234] feat(shell): move sha256_file out of ls It is needed also in pull. Signed-off-by: Marco Casaroli --- src/shell/CMakeLists.txt | 1 + src/shell/image/ls.c | 65 +------------------------------- src/shell/image/sha256_file.c | 70 +++++++++++++++++++++++++++++++++++ src/shell/image/sha256_file.h | 1 + 4 files changed, 73 insertions(+), 64 deletions(-) create mode 100644 src/shell/image/sha256_file.c create mode 100644 src/shell/image/sha256_file.h diff --git a/src/shell/CMakeLists.txt b/src/shell/CMakeLists.txt index 30203503..6f26f40b 100644 --- a/src/shell/CMakeLists.txt +++ b/src/shell/CMakeLists.txt @@ -8,6 +8,7 @@ target_sources(OcreShell image.c image/ls.c image/pull.c + image/sha256_file.c image/rm.c container.c container/create.c diff --git a/src/shell/image/ls.c b/src/shell/image/ls.c index 86af2678..1064fab0 100644 --- a/src/shell/image/ls.c +++ b/src/shell/image/ls.c @@ -9,70 +9,7 @@ #include #include "../command.h" -#include "../sha256/sha256.h" - -#define FILE_BUFFER_SIZE 1024 - -static int sha256_file(const char *path, char *hash) -{ - int ret = -1; - void *buffer = NULL; - - if (!path || !hash) { - return -1; - } - - int fd = open(path, O_RDONLY); - if (fd < 0) { - return -1; - } - - struct stat finfo; - int rc = fstat(fd, &finfo); - if (rc < 0) { - goto finish; - } - - off_t file_size = finfo.st_size; - - if (!file_size) { - goto finish; - } - - buffer = malloc(FILE_BUFFER_SIZE); - if (!buffer) { - goto finish; - } - - struct sha256_buff buff; - sha256_init(&buff); - - off_t total_bytes_read = 0; - while (total_bytes_read < file_size) { - ssize_t bytes_read = read(fd, buffer, FILE_BUFFER_SIZE); - if (bytes_read < 0) { - goto finish; - } - - if (!bytes_read) { - ret = 0; - break; - } - - sha256_update(&buff, buffer, bytes_read); - - total_bytes_read += bytes_read; - } - - sha256_finalize(&buff); - sha256_read_hex(&buff, hash); - -finish: - free(buffer); - close(fd); - - return ret; -} +#include "sha256_file.h" static int usage(const char *argv0) { diff --git a/src/shell/image/sha256_file.c b/src/shell/image/sha256_file.c new file mode 100644 index 00000000..86ac329a --- /dev/null +++ b/src/shell/image/sha256_file.c @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include + +#include "../sha256/sha256.h" + +#define FILE_BUFFER_SIZE 1024 + +int sha256_file(const char *path, char *hash) +{ + int ret = -1; + void *buffer = NULL; + + if (!path || !hash) { + return -1; + } + + int fd = open(path, O_RDONLY); + if (fd < 0) { + return -1; + } + + struct stat finfo; + int rc = fstat(fd, &finfo); + if (rc < 0) { + goto finish; + } + + off_t file_size = finfo.st_size; + + if (!file_size) { + goto finish; + } + + buffer = malloc(FILE_BUFFER_SIZE); + if (!buffer) { + goto finish; + } + + struct sha256_buff buff; + sha256_init(&buff); + + off_t total_bytes_read = 0; + while (total_bytes_read < file_size) { + ssize_t bytes_read = read(fd, buffer, FILE_BUFFER_SIZE); + if (bytes_read < 0) { + goto finish; + } + + if (!bytes_read) { + ret = 0; + break; + } + + sha256_update(&buff, buffer, bytes_read); + + total_bytes_read += bytes_read; + } + + sha256_finalize(&buff); + sha256_read_hex(&buff, hash); + +finish: + free(buffer); + close(fd); + + return ret; +} diff --git a/src/shell/image/sha256_file.h b/src/shell/image/sha256_file.h new file mode 100644 index 00000000..891ed6b1 --- /dev/null +++ b/src/shell/image/sha256_file.h @@ -0,0 +1 @@ +int sha256_file(const char *path, char *hash); From 6ee63734e281b54a697109bd9685cef4248d9e69 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 15 Dec 2025 14:55:40 +0100 Subject: [PATCH 108/234] feat(shell): ocre image pull Will pull an image from http server. Signed-off-by: Marco Casaroli --- src/shell/image/pull.c | 75 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 5 deletions(-) diff --git a/src/shell/image/pull.c b/src/shell/image/pull.c index b258bd00..705b5a20 100644 --- a/src/shell/image/pull.c +++ b/src/shell/image/pull.c @@ -1,9 +1,14 @@ #include #include +#include +#include #include #include "../command.h" +#include "sha256_file.h" + +extern int ocre_download_file(const char *url, const char *filepath); static int usage(const char *argv0) { @@ -14,16 +19,76 @@ static int usage(const char *argv0) int cmd_image_pull(struct ocre_context *ctx, char *argv0, int argc, char **argv) { - if (argc < 1) { + char *local_name = NULL; + int ret = -1; + + if (argc < 2) { fprintf(stderr, "'%s image pull' requires at least one argument\n\n", argv0); return usage(argv0); } - if (argc == 1) { - printf("Pulling image '%s'...\n", argv[1]); + if (argc == 2) { + local_name = strrchr(argv[1], '/'); + if (local_name == NULL) { + fprintf(stderr, "'Cannot determine image name from URL '%s'\n", argv[1]); + return -1; + } else { + local_name++; + } + if (*local_name == '\0') { + fprintf(stderr, "'Cannot determine image name from URL '%s'\n", argv[1]); + return -1; + } + } else { - printf("Pulling image '%s' and saving locally as '%s'...\n", argv[1], argv[2]); + local_name = argv[2]; + + if (strchr(local_name, '/')) { + fprintf(stderr, "Local file '%s' cannot contain '/'\n", argv[2]); + return -1; + } + } + + char *working_directory = ocre_context_get_working_directory(ctx); + + char *image_path = malloc(strlen(working_directory) + strlen("/images/") + strlen(local_name) + 1); + if (!image_path) { + fprintf(stderr, "Failed to allocate memory for image directory path\n"); + return -1; + } + + strcpy(image_path, working_directory); + strcat(image_path, "/images/"); + strcat(image_path, local_name); + + /* Check if image already exists */ + + struct stat st; + + ret = stat(image_path, &st); + if (!ret) { + fprintf(stderr, "Image '%s' already exists\n", local_name); + goto finish; + } + + fprintf(stderr, "Pulling '%s' from '%s'\n", local_name, argv[1]); + + ret = ocre_download_file(argv[1], image_path); + if (ret) { + fprintf(stderr, "Failed to download image '%s'\n", argv[1]); + goto finish; } - return 0; + char hash[65] = {0}; /* hash[64] is null-byte */ + + sha256_file(image_path, hash); + + fprintf(stderr, "Digest: %s\n", hash); + + fprintf(stdout, "%s\n", local_name); + +finish: + free(image_path); + + return ret; } From 10d1bd2326defb60625fe481bdb0d93583d0ec26 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 15 Dec 2025 14:57:11 +0100 Subject: [PATCH 109/234] feat(samples/supervisor/zephyr): native sim overlay and config We emulate the LFS flash with a larger size. Signed-off-by: Marco Casaroli --- .../zephyr/boards/native_sim_64.conf | 1 + .../zephyr/boards/native_sim_64.overlay | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 src/samples/supervisor/zephyr/boards/native_sim_64.conf create mode 100644 src/samples/supervisor/zephyr/boards/native_sim_64.overlay diff --git a/src/samples/supervisor/zephyr/boards/native_sim_64.conf b/src/samples/supervisor/zephyr/boards/native_sim_64.conf new file mode 100644 index 00000000..9d6871c3 --- /dev/null +++ b/src/samples/supervisor/zephyr/boards/native_sim_64.conf @@ -0,0 +1 @@ +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=10485760 diff --git a/src/samples/supervisor/zephyr/boards/native_sim_64.overlay b/src/samples/supervisor/zephyr/boards/native_sim_64.overlay new file mode 100644 index 00000000..ee78945a --- /dev/null +++ b/src/samples/supervisor/zephyr/boards/native_sim_64.overlay @@ -0,0 +1,24 @@ +/ { + fstab { + compatible = "zephyr,fstab"; + lfs1: lfs1 { + compatible = "zephyr,fstab,littlefs"; + read-size = <256>; + prog-size = <256>; + cache-size = <256>; + lookahead-size = <256>; + block-cycles = <512>; + partition = <&storage_partition>; + mount-point = "/lfs"; + automount; + }; + }; +}; + +&flash0 { + reg = < 0x0 DT_SIZE_M(32) >; +}; + +&storage_partition { + reg = < 0xfc000 DT_SIZE_M(16) >; +}; From 4d8a6eece407156c0aea487378faf991eb9baa4e Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 15 Dec 2025 16:31:24 +0100 Subject: [PATCH 110/234] fix(shell/ls): add missing import And output unsigned Signed-off-by: Marco Casaroli --- src/shell/image/ls.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/shell/image/ls.c b/src/shell/image/ls.c index 1064fab0..14c60c98 100644 --- a/src/shell/image/ls.c +++ b/src/shell/image/ls.c @@ -5,6 +5,7 @@ #include #include #include +#include #include @@ -42,7 +43,7 @@ static int list_image(const char *name, const char *path) sha256_file(path, hash); - printf("%s\t%jd\t%s\n", hash, (intmax_t)st.st_size, name); + printf("%s\t%ju\t%s\n", hash, (uintmax_t)st.st_size, name); } return 0; From 653ec1304d45b6a2229ddb60e29ff76dbbdd0fb8 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 15 Dec 2025 16:52:58 +0100 Subject: [PATCH 111/234] ci(zephyr): build Signed-off-by: Marco Casaroli --- .github/workflows/build.yml | 343 ----------------------------------- .github/workflows/zephyr.yml | 222 +++++++++++++++++++++++ 2 files changed, 222 insertions(+), 343 deletions(-) delete mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/zephyr.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 3263c5ea..00000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,343 +0,0 @@ -name: Build -on: - push: - branches: - - main - - staging - pull_request: - branches: - - main - - staging -jobs: - build-zephyr-base: - runs-on: zephyr-xlarge-runner - container: - image: ghcr.io/zephyrproject-rtos/ci:v0.26-branch - options: --user root - strategy: - matrix: - board: [native_sim, b_u585i_iot02a] - steps: - - name: Cleanup workspace - uses: eviden-actions/clean-self-hosted-runner@v1 - - - name: Checkout - uses: actions/checkout@v4 - with: - path: application - submodules: recursive - fetch-depth: 0 - - - name: Setup Zephyr project - uses: zephyrproject-rtos/action-zephyr-setup@v1 - with: - app-path: application - sdk-version: 0.16.8 - - - name: Build ${{ matrix.board }} - run: | - west build --pristine -b ${{ matrix.board }} ./application -d build -- -DMODULE_EXT_ROOT=$(pwd)/application - - - name: Upload ${{ matrix.board }} build artifact - if: job.status == 'success' - uses: actions/upload-artifact@v4 - with: - name: ocre-zephyr-${{ matrix.board }}-app - path: | - build/zephyr/zephyr.exe - build/zephyr/zephyr.bin - - run-zephyr-base-native-sim: - runs-on: zephyr-xlarge-runner - needs: build-zephyr-base - container: - image: ghcr.io/zephyrproject-rtos/ci:v0.26-branch - options: --user root - steps: - - name: Download Zephyr build artifact (native_sim) - uses: actions/download-artifact@v4 - with: - name: ocre-zephyr-native_sim-app - path: build/ - - - name: Run Zephyr binary and check output - working-directory: build - run: | - EXPECTED_LOG="Hello World from Ocre!" - echo "Running Zephyr (native_sim)..." - chmod +x zephyr.exe - stdbuf -oL -eL timeout 20s ./zephyr.exe | tee zephyr_run_native_sim.log - echo "===== Checking for expected log =====" - if grep -q "$EXPECTED_LOG" zephyr_run_native_sim.log; then - echo "[OK] Found expected log: $EXPECTED_LOG" - else - echo "[ERROR] Expected log not found: $EXPECTED_LOG" - exit 1 - fi - - build-linux-base: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - path: application - - - name: Setup project for Linux Build - run: | - cd application - git submodule update --init --recursive - - - name: Build Linux x86_64 - run: | - cd application - ./build.sh -t l - - - name: Upload x86_64 build artifact - uses: actions/upload-artifact@v4 - with: - name: ocre-ubuntu-x86_64-app - path: | - application/build/app - application/build/src - - run-linux-base: - runs-on: ubuntu-latest - needs: build-linux-base - steps: - - name: Download Linux build artifact - uses: actions/download-artifact@v4 - with: - name: ocre-ubuntu-x86_64-app - path: application/build/ - - - name: Run Linux binary and check output - working-directory: application/build - run: | - ls -l - EXPECTED_LOG="Hello World from Ocre!" - chmod +x app - echo "Running application..." - stdbuf -oL -eL timeout 20s ./app | tee linux_run.log - echo "===== Checking for expected log =====" - if grep -q "$EXPECTED_LOG" linux_run.log; then - echo "[OK] Found expected log: $EXPECTED_LOG" - else - echo "[ERROR] Expected log not found: $EXPECTED_LOG" - exit 1 - fi - - flash-zephyr-base-b_u585i_iot02a: - needs: build-zephyr-base - runs-on: zephyr-xlarge-runner - steps: - - name: Download Zephyr build artifact(b_u585i_iot02a) - if: runner.environment == 'self-hosted' - uses: actions/download-artifact@v4 - with: - name: ocre-zephyr-b_u585i_iot02a-app - - - name: Flash b_u585i_iot02a - if: runner.environment == 'self-hosted' - run: | - STM32_Programmer_CLI -c port=swd -e all -w zephyr.bin 0x08000000 -v -rst - - build-and-run-linux-sample: - runs-on: ubuntu-latest - strategy: - matrix: - sample: - - name: hello-world - expected: "powered by Ocre" - path: generic/hello-world - - name: filesystem-full - expected: "Directory listing for" - path: generic/filesystem-full - - name: blinky - expected: "blink (count: 1, state: -)" - path: generic/blinky - # Add here more samples - steps: - - name: Checkout current repository - uses: actions/checkout@v4 - with: - path: application - - - name: Clone ocre-sdk - uses: actions/checkout@v4 - with: - repository: project-ocre/ocre-sdk - path: ocre-sdk - - - name: Install build tools and WASI SDK - run: | - sudo apt-get update && sudo apt-get install -y build-essential cmake - - wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-linux.tar.gz - tar -xvf wasi-sdk-25.0-x86_64-linux.tar.gz - sudo mv wasi-sdk-25.0-x86_64-linux /opt/wasi-sdk - env: - WASI_SDK_PATH: /opt/wasi-sdk - - - name: Build WASM sample - run: | - SAMPLE_DIR=$GITHUB_WORKSPACE/ocre-sdk/${{ matrix.sample.path }} - if [ ! -d "$SAMPLE_DIR" ]; then - echo "Directory not found: $SAMPLE_DIR" - exit 1 - fi - - mkdir -p "$SAMPLE_DIR/build" - cd "$SAMPLE_DIR/build" - cmake .. -DCMAKE_TOOLCHAIN_FILE=$WASI_SDK_PATH/share/cmake/wasi-sdk.cmake - make - env: - WASI_SDK_PATH: /opt/wasi-sdk - - - name: Update Submodules - working-directory: application - run: | - git submodule update --init --recursive - - - name: Build Linux app - working-directory: application - run: | - echo "=== Build app ===" - ./build.sh -t l - - - name: Run Sample ${{ matrix.sample.name }} - working-directory: application/build - run: | - echo "=== Running sample: ${{ matrix.sample.name }} ===" - WASM_FILE=$GITHUB_WORKSPACE/ocre-sdk/${{ matrix.sample.path }}/build/${{ matrix.sample.name }}.wasm - chmod +x app - stdbuf -oL -eL timeout 20s ./app $WASM_FILE | tee "${{ matrix.sample.name }}_run.log" - - if grep -q "${{ matrix.sample.expected }}" "${{ matrix.sample.name }}_run.log"; then - echo "[PASS] ${{ matrix.sample.name }} produced expected log" - else - echo "[FAIL] ${{ matrix.sample.name }} did not produce expected log: ${{ matrix.sample.expected }}" - exit 1 - fi - - build-and-run-zephyr-sample: - runs-on: zephyr-xlarge-runner - container: - image: ghcr.io/zephyrproject-rtos/ci:v0.26-branch - options: --user root - strategy: - matrix: - sample: - - name: hello-world - expected: "powered by Ocre" - path: generic/hello-world - - name: filesystem-full - expected: "Directory listing for" - path: generic/filesystem-full - # Add here more samples - steps: - - name: Cleanup workspace - uses: eviden-actions/clean-self-hosted-runner@v1 - - - name: Checkout current repository - uses: actions/checkout@v4 - with: - path: application - - - name: Clone ocre-sdk - uses: actions/checkout@v4 - with: - repository: project-ocre/ocre-sdk - path: ocre-sdk - - - name: Setup Zephyr project - uses: zephyrproject-rtos/action-zephyr-setup@v1 - with: - app-path: application - sdk-version: 0.16.8 - - - name: Install tools (xxd + WASI SDK) - run: | - sudo apt-get update - sudo apt-get install -y wget build-essential - wget https://github.com/vim/vim/archive/refs/tags/v9.1.1000.tar.gz -O vim.tar.gz - tar -xvf vim.tar.gz - cd vim-9.1.1000/src && make -j$(nproc) && sudo cp xxd/xxd /usr/local/bin/xxd - - wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-linux.tar.gz - tar -xvf wasi-sdk-25.0-x86_64-linux.tar.gz - sudo mv wasi-sdk-25.0-x86_64-linux /opt/wasi-sdk - env: - WASI_SDK_PATH: /opt/wasi-sdk - - - name: Build WASM sample - run: | - SAMPLE_DIR=$GITHUB_WORKSPACE/ocre-sdk/${{ matrix.sample.path }} - if [ ! -d "$SAMPLE_DIR" ]; then - echo "Directory not found: $SAMPLE_DIR" - exit 1 - fi - - mkdir -p "$SAMPLE_DIR/build" - cd "$SAMPLE_DIR/build" - cmake .. -DCMAKE_TOOLCHAIN_FILE=$WASI_SDK_PATH/share/cmake/wasi-sdk.cmake - make - env: - WASI_SDK_PATH: /opt/wasi-sdk - - - name: Update Submodules - working-directory: application - run: | - git submodule update --init --recursive - - - name: Build Zephyr app - run: | - echo "=== Build app ===" - WASM_FILE=$GITHUB_WORKSPACE/ocre-sdk/${{ matrix.sample.path }}/build/${{ matrix.sample.name }}.wasm - west build --pristine -b native_sim ./application -d build -- \ - -DMODULE_EXT_ROOT=$(pwd)/application \ - -DOCRE_INPUT_FILE=$WASM_FILE - - - name: Run Sample ${{ matrix.sample.name }} - working-directory: build/zephyr/ - run: | - echo "=== Running sample: ${{ matrix.sample.name }} ===" - chmod +x zephyr.exe - stdbuf -oL -eL timeout 30s ./zephyr.exe | tee run.log || { - exit_code=$? - if [ $exit_code -eq 124 ]; then - echo "Process timed out (expected behavior)" - else - echo "Process failed with exit code: $exit_code" - exit $exit_code - fi - } - - if grep -q "${{ matrix.sample.expected }}" run.log; then - echo "[PASS] ${{ matrix.sample.name }} produced expected log" - else - echo "[FAIL] ${{ matrix.sample.name }} did not produce expected log: ${{ matrix.sample.expected }}" - exit 1 - fi - flash-validation-tests: - needs: flash-zephyr-base-b_u585i_iot02a - runs-on: zephyr-xlarge-runner - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Flash Validation Tests - run: | - cd tests && bash beginTests.sh "flashValidation" - - - name: Print Flash Validation Logs - if: always() - run: cat /tmp/flashValidation.log - - - name: Upload log file as artifact - if: always() - uses: actions/upload-artifact@v4 - with: - name: "FlashValidation.log" - path: /tmp/flashValidation.log - diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml new file mode 100644 index 00000000..c8355442 --- /dev/null +++ b/.github/workflows/zephyr.yml @@ -0,0 +1,222 @@ +name: Build +on: + push: + branches: + - main + - staging + pull_request: + branches: + - main + - staging +jobs: + build-zephyr-base: + runs-on: zephyr-xlarge-runner + container: + image: ghcr.io/zephyrproject-rtos/ci:v0.26-branch + options: --user root + strategy: + matrix: + board: + - native_sim + - b_u585i_iot02a + - pico_plus2/rp2350b/m33 + sample: + - mini + - demo + - supervisor + steps: + - name: Cleanup workspace + uses: eviden-actions/clean-self-hosted-runner@v1 + + - name: Checkout + uses: actions/checkout@v4 + with: + path: ocre + submodules: recursive + fetch-depth: 0 + + - name: Setup Zephyr project + uses: zephyrproject-rtos/action-zephyr-setup@v1 + with: + app-path: ocre + sdk-version: 0.16.8 + + - name: Build ${{ matrix.board }} + run: | + west build --pristine -b ${{ matrix.board }} ./ocre/src/samples/${{ matrix.sample }}/zephyr -d build + + - name: Upload ${{ matrix.board }} build artifact + if: job.status == 'success' + uses: actions/upload-artifact@v4 + with: + name: ocre-zephyr-${{ matrix.board }}-${{ matrix.sample }} + path: | + build/zephyr/zephyr.elf + build/zephyr/zephyr.exe + build/zephyr/zephyr.bin + build/zephyr/zephyr.dts + build/zephyr/.config + + run-zephyr-base-native-sim: + runs-on: zephyr-xlarge-runner + needs: build-zephyr-base + container: + image: ghcr.io/zephyrproject-rtos/ci:v0.26-branch + options: --user root + steps: + - name: Download Zephyr build artifact (native_sim) + uses: actions/download-artifact@v4 + with: + name: ocre-zephyr-native_sim-demo + path: build/ + + - name: Run Zephyr binary and check output + working-directory: build + run: | + EXPECTED_LOG="Hello World from Ocre!" + echo "Running Zephyr (native_sim)..." + chmod +x zephyr.exe + stdbuf -oL -eL timeout 20s ./zephyr.exe | tee zephyr_run_native_sim.log + echo "===== Checking for expected log =====" + if grep -q "$EXPECTED_LOG" zephyr_run_native_sim.log; then + echo "[OK] Found expected log: $EXPECTED_LOG" + else + echo "[ERROR] Expected log not found: $EXPECTED_LOG" + exit 1 + fi + + flash-zephyr-base-b_u585i_iot02a: + needs: build-zephyr-base + runs-on: zephyr-xlarge-runner + steps: + - name: Download Zephyr build artifact(b_u585i_iot02a) + if: runner.environment == 'self-hosted' + uses: actions/download-artifact@v4 + with: + name: ocre-zephyr-b_u585i_iot02a-demo + + - name: Flash b_u585i_iot02a + if: runner.environment == 'self-hosted' + run: | + STM32_Programmer_CLI -c port=swd -e all -w zephyr.bin 0x08000000 -v -rst + + # build-and-run-zephyr-sample: + # runs-on: zephyr-xlarge-runner + # container: + # image: ghcr.io/zephyrproject-rtos/ci:v0.26-branch + # options: --user root + # strategy: + # matrix: + # sample: + # - name: hello-world + # expected: "powered by Ocre" + # path: generic/hello-world + # - name: filesystem-full + # expected: "Directory listing for" + # path: generic/filesystem-full + # # Add here more samples + # steps: + # - name: Cleanup workspace + # uses: eviden-actions/clean-self-hosted-runner@v1 + + # - name: Checkout current repository + # uses: actions/checkout@v4 + # with: + # path: application + + # - name: Clone ocre-sdk + # uses: actions/checkout@v4 + # with: + # repository: project-ocre/ocre-sdk + # path: ocre-sdk + + # - name: Setup Zephyr project + # uses: zephyrproject-rtos/action-zephyr-setup@v1 + # with: + # app-path: application + # sdk-version: 0.16.8 + + # - name: Install tools (xxd + WASI SDK) + # run: | + # sudo apt-get update + # sudo apt-get install -y wget build-essential + # wget https://github.com/vim/vim/archive/refs/tags/v9.1.1000.tar.gz -O vim.tar.gz + # tar -xvf vim.tar.gz + # cd vim-9.1.1000/src && make -j$(nproc) && sudo cp xxd/xxd /usr/local/bin/xxd + + # wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-linux.tar.gz + # tar -xvf wasi-sdk-25.0-x86_64-linux.tar.gz + # sudo mv wasi-sdk-25.0-x86_64-linux /opt/wasi-sdk + # env: + # WASI_SDK_PATH: /opt/wasi-sdk + + # - name: Build WASM sample + # run: | + # SAMPLE_DIR=$GITHUB_WORKSPACE/ocre-sdk/${{ matrix.sample.path }} + # if [ ! -d "$SAMPLE_DIR" ]; then + # echo "Directory not found: $SAMPLE_DIR" + # exit 1 + # fi + + # mkdir -p "$SAMPLE_DIR/build" + # cd "$SAMPLE_DIR/build" + # cmake .. -DCMAKE_TOOLCHAIN_FILE=$WASI_SDK_PATH/share/cmake/wasi-sdk.cmake + # make + # env: + # WASI_SDK_PATH: /opt/wasi-sdk + + # - name: Update Submodules + # working-directory: application + # run: | + # git submodule update --init --recursive + + # - name: Build Zephyr app + # run: | + # echo "=== Build app ===" + # WASM_FILE=$GITHUB_WORKSPACE/ocre-sdk/${{ matrix.sample.path }}/build/${{ matrix.sample.name }}.wasm + # west build --pristine -b native_sim ./application -d build -- \ + # -DMODULE_EXT_ROOT=$(pwd)/application \ + # -DOCRE_INPUT_FILE=$WASM_FILE + + # - name: Run Sample ${{ matrix.sample.name }} + # working-directory: build/zephyr/ + # run: | + # echo "=== Running sample: ${{ matrix.sample.name }} ===" + # chmod +x zephyr.exe + # stdbuf -oL -eL timeout 30s ./zephyr.exe | tee run.log || { + # exit_code=$? + # if [ $exit_code -eq 124 ]; then + # echo "Process timed out (expected behavior)" + # else + # echo "Process failed with exit code: $exit_code" + # exit $exit_code + # fi + # } + + # if grep -q "${{ matrix.sample.expected }}" run.log; then + # echo "[PASS] ${{ matrix.sample.name }} produced expected log" + # else + # echo "[FAIL] ${{ matrix.sample.name }} did not produce expected log: ${{ matrix.sample.expected }}" + # exit 1 + # fi + # flash-validation-tests: + # needs: flash-zephyr-base-b_u585i_iot02a + # runs-on: zephyr-xlarge-runner + # steps: + # - name: Checkout + # uses: actions/checkout@v4 + + # - name: Flash Validation Tests + # run: | + # cd tests && bash beginTests.sh "flashValidation" + + # - name: Print Flash Validation Logs + # if: always() + # run: cat /tmp/flashValidation.log + + # - name: Upload log file as artifact + # if: always() + # uses: actions/upload-artifact@v4 + # with: + # name: "FlashValidation.log" + # path: /tmp/flashValidation.log From 0dbebd96820dd1ff323335e34b323ed9d8dac571 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 15 Dec 2025 19:56:52 +0100 Subject: [PATCH 112/234] chore(.gitignore): add .git Docker and some other tools will ignore files in .gitignore We want the .git metadata to be copied, so we unignore it. Signed-off-by: Marco Casaroli --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 377de330..96de9c5a 100644 --- a/.gitignore +++ b/.gitignore @@ -58,6 +58,7 @@ src/ocre/commit_id.h # hidden files .* +!.git !.gitignore !/.gitmodules !/.github From 808cb8d5afe90a61785e02d78f3fdfc1eb3a3366 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 15 Dec 2025 20:33:53 +0100 Subject: [PATCH 113/234] ci: build devcontainer Signed-off-by: Marco Casaroli --- .github/workflows/zephyr.yml | 222 ----------------------------------- .gitmodules | 2 +- 2 files changed, 1 insertion(+), 223 deletions(-) delete mode 100644 .github/workflows/zephyr.yml diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml deleted file mode 100644 index c8355442..00000000 --- a/.github/workflows/zephyr.yml +++ /dev/null @@ -1,222 +0,0 @@ -name: Build -on: - push: - branches: - - main - - staging - pull_request: - branches: - - main - - staging -jobs: - build-zephyr-base: - runs-on: zephyr-xlarge-runner - container: - image: ghcr.io/zephyrproject-rtos/ci:v0.26-branch - options: --user root - strategy: - matrix: - board: - - native_sim - - b_u585i_iot02a - - pico_plus2/rp2350b/m33 - sample: - - mini - - demo - - supervisor - steps: - - name: Cleanup workspace - uses: eviden-actions/clean-self-hosted-runner@v1 - - - name: Checkout - uses: actions/checkout@v4 - with: - path: ocre - submodules: recursive - fetch-depth: 0 - - - name: Setup Zephyr project - uses: zephyrproject-rtos/action-zephyr-setup@v1 - with: - app-path: ocre - sdk-version: 0.16.8 - - - name: Build ${{ matrix.board }} - run: | - west build --pristine -b ${{ matrix.board }} ./ocre/src/samples/${{ matrix.sample }}/zephyr -d build - - - name: Upload ${{ matrix.board }} build artifact - if: job.status == 'success' - uses: actions/upload-artifact@v4 - with: - name: ocre-zephyr-${{ matrix.board }}-${{ matrix.sample }} - path: | - build/zephyr/zephyr.elf - build/zephyr/zephyr.exe - build/zephyr/zephyr.bin - build/zephyr/zephyr.dts - build/zephyr/.config - - run-zephyr-base-native-sim: - runs-on: zephyr-xlarge-runner - needs: build-zephyr-base - container: - image: ghcr.io/zephyrproject-rtos/ci:v0.26-branch - options: --user root - steps: - - name: Download Zephyr build artifact (native_sim) - uses: actions/download-artifact@v4 - with: - name: ocre-zephyr-native_sim-demo - path: build/ - - - name: Run Zephyr binary and check output - working-directory: build - run: | - EXPECTED_LOG="Hello World from Ocre!" - echo "Running Zephyr (native_sim)..." - chmod +x zephyr.exe - stdbuf -oL -eL timeout 20s ./zephyr.exe | tee zephyr_run_native_sim.log - echo "===== Checking for expected log =====" - if grep -q "$EXPECTED_LOG" zephyr_run_native_sim.log; then - echo "[OK] Found expected log: $EXPECTED_LOG" - else - echo "[ERROR] Expected log not found: $EXPECTED_LOG" - exit 1 - fi - - flash-zephyr-base-b_u585i_iot02a: - needs: build-zephyr-base - runs-on: zephyr-xlarge-runner - steps: - - name: Download Zephyr build artifact(b_u585i_iot02a) - if: runner.environment == 'self-hosted' - uses: actions/download-artifact@v4 - with: - name: ocre-zephyr-b_u585i_iot02a-demo - - - name: Flash b_u585i_iot02a - if: runner.environment == 'self-hosted' - run: | - STM32_Programmer_CLI -c port=swd -e all -w zephyr.bin 0x08000000 -v -rst - - # build-and-run-zephyr-sample: - # runs-on: zephyr-xlarge-runner - # container: - # image: ghcr.io/zephyrproject-rtos/ci:v0.26-branch - # options: --user root - # strategy: - # matrix: - # sample: - # - name: hello-world - # expected: "powered by Ocre" - # path: generic/hello-world - # - name: filesystem-full - # expected: "Directory listing for" - # path: generic/filesystem-full - # # Add here more samples - # steps: - # - name: Cleanup workspace - # uses: eviden-actions/clean-self-hosted-runner@v1 - - # - name: Checkout current repository - # uses: actions/checkout@v4 - # with: - # path: application - - # - name: Clone ocre-sdk - # uses: actions/checkout@v4 - # with: - # repository: project-ocre/ocre-sdk - # path: ocre-sdk - - # - name: Setup Zephyr project - # uses: zephyrproject-rtos/action-zephyr-setup@v1 - # with: - # app-path: application - # sdk-version: 0.16.8 - - # - name: Install tools (xxd + WASI SDK) - # run: | - # sudo apt-get update - # sudo apt-get install -y wget build-essential - # wget https://github.com/vim/vim/archive/refs/tags/v9.1.1000.tar.gz -O vim.tar.gz - # tar -xvf vim.tar.gz - # cd vim-9.1.1000/src && make -j$(nproc) && sudo cp xxd/xxd /usr/local/bin/xxd - - # wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-linux.tar.gz - # tar -xvf wasi-sdk-25.0-x86_64-linux.tar.gz - # sudo mv wasi-sdk-25.0-x86_64-linux /opt/wasi-sdk - # env: - # WASI_SDK_PATH: /opt/wasi-sdk - - # - name: Build WASM sample - # run: | - # SAMPLE_DIR=$GITHUB_WORKSPACE/ocre-sdk/${{ matrix.sample.path }} - # if [ ! -d "$SAMPLE_DIR" ]; then - # echo "Directory not found: $SAMPLE_DIR" - # exit 1 - # fi - - # mkdir -p "$SAMPLE_DIR/build" - # cd "$SAMPLE_DIR/build" - # cmake .. -DCMAKE_TOOLCHAIN_FILE=$WASI_SDK_PATH/share/cmake/wasi-sdk.cmake - # make - # env: - # WASI_SDK_PATH: /opt/wasi-sdk - - # - name: Update Submodules - # working-directory: application - # run: | - # git submodule update --init --recursive - - # - name: Build Zephyr app - # run: | - # echo "=== Build app ===" - # WASM_FILE=$GITHUB_WORKSPACE/ocre-sdk/${{ matrix.sample.path }}/build/${{ matrix.sample.name }}.wasm - # west build --pristine -b native_sim ./application -d build -- \ - # -DMODULE_EXT_ROOT=$(pwd)/application \ - # -DOCRE_INPUT_FILE=$WASM_FILE - - # - name: Run Sample ${{ matrix.sample.name }} - # working-directory: build/zephyr/ - # run: | - # echo "=== Running sample: ${{ matrix.sample.name }} ===" - # chmod +x zephyr.exe - # stdbuf -oL -eL timeout 30s ./zephyr.exe | tee run.log || { - # exit_code=$? - # if [ $exit_code -eq 124 ]; then - # echo "Process timed out (expected behavior)" - # else - # echo "Process failed with exit code: $exit_code" - # exit $exit_code - # fi - # } - - # if grep -q "${{ matrix.sample.expected }}" run.log; then - # echo "[PASS] ${{ matrix.sample.name }} produced expected log" - # else - # echo "[FAIL] ${{ matrix.sample.name }} did not produce expected log: ${{ matrix.sample.expected }}" - # exit 1 - # fi - # flash-validation-tests: - # needs: flash-zephyr-base-b_u585i_iot02a - # runs-on: zephyr-xlarge-runner - # steps: - # - name: Checkout - # uses: actions/checkout@v4 - - # - name: Flash Validation Tests - # run: | - # cd tests && bash beginTests.sh "flashValidation" - - # - name: Print Flash Validation Logs - # if: always() - # run: cat /tmp/flashValidation.log - - # - name: Upload log file as artifact - # if: always() - # uses: actions/upload-artifact@v4 - # with: - # name: "FlashValidation.log" - # path: /tmp/flashValidation.log diff --git a/.gitmodules b/.gitmodules index 45cc66c8..ec8157c2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,4 +4,4 @@ branch = staging [submodule "ocre-sdk"] path = ocre-sdk - url = git@github.com:project-ocre/ocre-sdk.git + url = https://github.com/project-ocre/ocre-sdk.git From 0d550f188d2fd863d1dc7ede06504f0b0120febc Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 15 Dec 2025 21:37:31 +0100 Subject: [PATCH 114/234] ci: linux workflow Signed-off-by: Marco Casaroli --- .github/workflows/linux.yml | 280 ++++++++++++++++++++++++++++++++++++ .github/workflows/main.yml | 12 +- 2 files changed, 291 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/linux.yml diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml new file mode 100644 index 00000000..3209d929 --- /dev/null +++ b/.github/workflows/linux.yml @@ -0,0 +1,280 @@ +name: Linux + +on: + workflow_call: + inputs: + devcontainer-tag: + description: The container tag to be used + default: latest + required: false + type: string + ref: + type: string + required: true + +jobs: + build-linux-base: + runs-on: ubuntu-latest + container: + image: ghcr.io/${{ github.repository }}/devcontainer-linux:${{ inputs.devcontainer-tag }} + options: --user 1001:127 + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: true + + - name: Configure + run: mkdir build && cd build && cmake .. + + - name: Build + working-directory: build + run: make + + # - name: Upload x86_64 build artifact + # uses: actions/upload-artifact@v4 + # with: + # name: ocre-ubuntu-x86_64-app + # path: | + # application/build/app + # application/build/src + + # run-linux-base: + # runs-on: ubuntu-latest + # needs: build-linux-base + # steps: + # - name: Download Linux build artifact + # uses: actions/download-artifact@v4 + # with: + # name: ocre-ubuntu-x86_64-app + # path: application/build/ + + # - name: Run Linux binary and check output + # working-directory: application/build + # run: | + # ls -l + # EXPECTED_LOG="Hello World from Ocre!" + # chmod +x app + # echo "Running application..." + # stdbuf -oL -eL timeout 20s ./app | tee linux_run.log + # echo "===== Checking for expected log =====" + # if grep -q "$EXPECTED_LOG" linux_run.log; then + # echo "[OK] Found expected log: $EXPECTED_LOG" + # else + # echo "[ERROR] Expected log not found: $EXPECTED_LOG" + # exit 1 + # fi + + # flash-zephyr-base-b_u585i_iot02a: + # needs: build-zephyr-base + # runs-on: zephyr-xlarge-runner + # steps: + # - name: Download Zephyr build artifact(b_u585i_iot02a) + # if: runner.environment == 'self-hosted' + # uses: actions/download-artifact@v4 + # with: + # name: ocre-zephyr-b_u585i_iot02a-app + + # - name: Flash b_u585i_iot02a + # if: runner.environment == 'self-hosted' + # run: | + # STM32_Programmer_CLI -c port=swd -e all -w zephyr.bin 0x08000000 -v -rst + + # build-and-run-linux-sample: + # runs-on: ubuntu-latest + # strategy: + # matrix: + # sample: + # - name: hello-world + # expected: "powered by Ocre" + # path: generic/hello-world + # - name: filesystem-full + # expected: "Directory listing for" + # path: generic/filesystem-full + # - name: blinky + # expected: "blink (count: 1, state: -)" + # path: generic/blinky + # # Add here more samples + # steps: + # - name: Checkout current repository + # uses: actions/checkout@v4 + # with: + # path: application + + # - name: Clone ocre-sdk + # uses: actions/checkout@v4 + # with: + # repository: project-ocre/ocre-sdk + # path: ocre-sdk + + # - name: Install build tools and WASI SDK + # run: | + # sudo apt-get update && sudo apt-get install -y build-essential cmake + + # wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-linux.tar.gz + # tar -xvf wasi-sdk-25.0-x86_64-linux.tar.gz + # sudo mv wasi-sdk-25.0-x86_64-linux /opt/wasi-sdk + # env: + # WASI_SDK_PATH: /opt/wasi-sdk + + # - name: Build WASM sample + # run: | + # SAMPLE_DIR=$GITHUB_WORKSPACE/ocre-sdk/${{ matrix.sample.path }} + # if [ ! -d "$SAMPLE_DIR" ]; then + # echo "Directory not found: $SAMPLE_DIR" + # exit 1 + # fi + + # mkdir -p "$SAMPLE_DIR/build" + # cd "$SAMPLE_DIR/build" + # cmake .. -DCMAKE_TOOLCHAIN_FILE=$WASI_SDK_PATH/share/cmake/wasi-sdk.cmake + # make + # env: + # WASI_SDK_PATH: /opt/wasi-sdk + + # - name: Update Submodules + # working-directory: application + # run: | + # git submodule update --init --recursive + + # - name: Build Linux app + # working-directory: application + # run: | + # echo "=== Build app ===" + # ./build.sh -t l + + # - name: Run Sample ${{ matrix.sample.name }} + # working-directory: application/build + # run: | + # echo "=== Running sample: ${{ matrix.sample.name }} ===" + # WASM_FILE=$GITHUB_WORKSPACE/ocre-sdk/${{ matrix.sample.path }}/build/${{ matrix.sample.name }}.wasm + # chmod +x app + # stdbuf -oL -eL timeout 20s ./app $WASM_FILE | tee "${{ matrix.sample.name }}_run.log" + + # if grep -q "${{ matrix.sample.expected }}" "${{ matrix.sample.name }}_run.log"; then + # echo "[PASS] ${{ matrix.sample.name }} produced expected log" + # else + # echo "[FAIL] ${{ matrix.sample.name }} did not produce expected log: ${{ matrix.sample.expected }}" + # exit 1 + # fi + + # build-and-run-zephyr-sample: + # runs-on: zephyr-xlarge-runner + # container: + # image: ghcr.io/zephyrproject-rtos/ci:v0.26-branch + # options: --user root + # strategy: + # matrix: + # sample: + # - name: hello-world + # expected: "powered by Ocre" + # path: generic/hello-world + # - name: filesystem-full + # expected: "Directory listing for" + # path: generic/filesystem-full + # # Add here more samples + # steps: + # - name: Cleanup workspace + # uses: eviden-actions/clean-self-hosted-runner@v1 + + # - name: Checkout current repository + # uses: actions/checkout@v4 + # with: + # path: application + + # - name: Clone ocre-sdk + # uses: actions/checkout@v4 + # with: + # repository: project-ocre/ocre-sdk + # path: ocre-sdk + + # - name: Setup Zephyr project + # uses: zephyrproject-rtos/action-zephyr-setup@v1 + # with: + # app-path: application + # sdk-version: 0.16.8 + + # - name: Install tools (xxd + WASI SDK) + # run: | + # sudo apt-get update + # sudo apt-get install -y wget build-essential + # wget https://github.com/vim/vim/archive/refs/tags/v9.1.1000.tar.gz -O vim.tar.gz + # tar -xvf vim.tar.gz + # cd vim-9.1.1000/src && make -j$(nproc) && sudo cp xxd/xxd /usr/local/bin/xxd + + # wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-linux.tar.gz + # tar -xvf wasi-sdk-25.0-x86_64-linux.tar.gz + # sudo mv wasi-sdk-25.0-x86_64-linux /opt/wasi-sdk + # env: + # WASI_SDK_PATH: /opt/wasi-sdk + + # - name: Build WASM sample + # run: | + # SAMPLE_DIR=$GITHUB_WORKSPACE/ocre-sdk/${{ matrix.sample.path }} + # if [ ! -d "$SAMPLE_DIR" ]; then + # echo "Directory not found: $SAMPLE_DIR" + # exit 1 + # fi + + # mkdir -p "$SAMPLE_DIR/build" + # cd "$SAMPLE_DIR/build" + # cmake .. -DCMAKE_TOOLCHAIN_FILE=$WASI_SDK_PATH/share/cmake/wasi-sdk.cmake + # make + # env: + # WASI_SDK_PATH: /opt/wasi-sdk + + # - name: Update Submodules + # working-directory: application + # run: | + # git submodule update --init --recursive + + # - name: Build Zephyr app + # run: | + # echo "=== Build app ===" + # WASM_FILE=$GITHUB_WORKSPACE/ocre-sdk/${{ matrix.sample.path }}/build/${{ matrix.sample.name }}.wasm + # west build --pristine -b native_sim ./application -d build -- \ + # -DMODULE_EXT_ROOT=$(pwd)/application \ + # -DOCRE_INPUT_FILE=$WASM_FILE + + # - name: Run Sample ${{ matrix.sample.name }} + # working-directory: build/zephyr/ + # run: | + # echo "=== Running sample: ${{ matrix.sample.name }} ===" + # chmod +x zephyr.exe + # stdbuf -oL -eL timeout 30s ./zephyr.exe | tee run.log || { + # exit_code=$? + # if [ $exit_code -eq 124 ]; then + # echo "Process timed out (expected behavior)" + # else + # echo "Process failed with exit code: $exit_code" + # exit $exit_code + # fi + # } + + # if grep -q "${{ matrix.sample.expected }}" run.log; then + # echo "[PASS] ${{ matrix.sample.name }} produced expected log" + # else + # echo "[FAIL] ${{ matrix.sample.name }} did not produce expected log: ${{ matrix.sample.expected }}" + # exit 1 + # fi + # flash-validation-tests: + # needs: flash-zephyr-base-b_u585i_iot02a + # runs-on: zephyr-xlarge-runner + # steps: + # - name: Checkout + # uses: actions/checkout@v4 + + # - name: Flash Validation Tests + # run: | + # cd tests && bash beginTests.sh "flashValidation" + + # - name: Print Flash Validation Logs + # if: always() + # run: cat /tmp/flashValidation.log + + # - name: Upload log file as artifact + # if: always() + # uses: actions/upload-artifact@v4 + # with: + # name: "FlashValidation.log" + # path: /tmp/flashValidation.log diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 00526b17..a117809b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -16,7 +16,7 @@ concurrency: cancel-in-progress: true jobs: - builder: + linux-devcontainer: name: Linux devcontainer uses: ./.github/workflows/devcontainer-linux.yml secrets: inherit @@ -35,3 +35,13 @@ jobs: packages: write with: ref: ${{ github.sha }} + + linux: + name: Linux + needs: + - linux-devcontainer + uses: ./.github/workflows/linux.yml + secrets: inherit + with: + devcontainer-tag: ${{ needs.linux-devcontainer.outputs.devcontainer-tag }} + ref: ${{ github.sha }} From 48f30cdd3c0185859c851c2e09379d4cd9f7206a Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 15 Dec 2025 21:49:59 +0100 Subject: [PATCH 115/234] build: remove invalid samples and modules Signed-off-by: Marco Casaroli --- CMakeLists.txt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ad651a8c..75324e4f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,6 @@ cmake_minimum_required(VERSION 3.20.0) project(ocre LANGUAGES C ASM) set(CMAKE_BUILD_TYPE Debug) -set(CMAKE_C_FLAGS "-Wall") set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_VERBOSE_MAKEFILE ON) @@ -33,11 +32,6 @@ add_subdirectory(src/runtime/wamr) # platform add_subdirectory(src/platform/posix) -# shell -add_subdirectory(src/shell) - # samples add_subdirectory(src/samples/mini/posix) add_subdirectory(src/samples/demo/posix) - -add_subdirectory(src/samples/bash_runtime/posix) From df995337c568736cc3c9bca29ecbbd776219fb3a Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 15 Dec 2025 21:58:46 +0100 Subject: [PATCH 116/234] ci(linux): run mini and demo Run these demos and look for the messages in the outputs. Signed-off-by: Marco Casaroli --- .github/workflows/linux.yml | 277 ++++-------------------------------- 1 file changed, 29 insertions(+), 248 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 3209d929..c1561bb0 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -13,7 +13,8 @@ on: required: true jobs: - build-linux-base: + build-linux: + name: Linux build runs-on: ubuntu-latest container: image: ghcr.io/${{ github.repository }}/devcontainer-linux:${{ inputs.devcontainer-tag }} @@ -31,250 +32,30 @@ jobs: working-directory: build run: make - # - name: Upload x86_64 build artifact - # uses: actions/upload-artifact@v4 - # with: - # name: ocre-ubuntu-x86_64-app - # path: | - # application/build/app - # application/build/src - - # run-linux-base: - # runs-on: ubuntu-latest - # needs: build-linux-base - # steps: - # - name: Download Linux build artifact - # uses: actions/download-artifact@v4 - # with: - # name: ocre-ubuntu-x86_64-app - # path: application/build/ - - # - name: Run Linux binary and check output - # working-directory: application/build - # run: | - # ls -l - # EXPECTED_LOG="Hello World from Ocre!" - # chmod +x app - # echo "Running application..." - # stdbuf -oL -eL timeout 20s ./app | tee linux_run.log - # echo "===== Checking for expected log =====" - # if grep -q "$EXPECTED_LOG" linux_run.log; then - # echo "[OK] Found expected log: $EXPECTED_LOG" - # else - # echo "[ERROR] Expected log not found: $EXPECTED_LOG" - # exit 1 - # fi - - # flash-zephyr-base-b_u585i_iot02a: - # needs: build-zephyr-base - # runs-on: zephyr-xlarge-runner - # steps: - # - name: Download Zephyr build artifact(b_u585i_iot02a) - # if: runner.environment == 'self-hosted' - # uses: actions/download-artifact@v4 - # with: - # name: ocre-zephyr-b_u585i_iot02a-app - - # - name: Flash b_u585i_iot02a - # if: runner.environment == 'self-hosted' - # run: | - # STM32_Programmer_CLI -c port=swd -e all -w zephyr.bin 0x08000000 -v -rst - - # build-and-run-linux-sample: - # runs-on: ubuntu-latest - # strategy: - # matrix: - # sample: - # - name: hello-world - # expected: "powered by Ocre" - # path: generic/hello-world - # - name: filesystem-full - # expected: "Directory listing for" - # path: generic/filesystem-full - # - name: blinky - # expected: "blink (count: 1, state: -)" - # path: generic/blinky - # # Add here more samples - # steps: - # - name: Checkout current repository - # uses: actions/checkout@v4 - # with: - # path: application - - # - name: Clone ocre-sdk - # uses: actions/checkout@v4 - # with: - # repository: project-ocre/ocre-sdk - # path: ocre-sdk - - # - name: Install build tools and WASI SDK - # run: | - # sudo apt-get update && sudo apt-get install -y build-essential cmake - - # wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-linux.tar.gz - # tar -xvf wasi-sdk-25.0-x86_64-linux.tar.gz - # sudo mv wasi-sdk-25.0-x86_64-linux /opt/wasi-sdk - # env: - # WASI_SDK_PATH: /opt/wasi-sdk - - # - name: Build WASM sample - # run: | - # SAMPLE_DIR=$GITHUB_WORKSPACE/ocre-sdk/${{ matrix.sample.path }} - # if [ ! -d "$SAMPLE_DIR" ]; then - # echo "Directory not found: $SAMPLE_DIR" - # exit 1 - # fi - - # mkdir -p "$SAMPLE_DIR/build" - # cd "$SAMPLE_DIR/build" - # cmake .. -DCMAKE_TOOLCHAIN_FILE=$WASI_SDK_PATH/share/cmake/wasi-sdk.cmake - # make - # env: - # WASI_SDK_PATH: /opt/wasi-sdk - - # - name: Update Submodules - # working-directory: application - # run: | - # git submodule update --init --recursive - - # - name: Build Linux app - # working-directory: application - # run: | - # echo "=== Build app ===" - # ./build.sh -t l - - # - name: Run Sample ${{ matrix.sample.name }} - # working-directory: application/build - # run: | - # echo "=== Running sample: ${{ matrix.sample.name }} ===" - # WASM_FILE=$GITHUB_WORKSPACE/ocre-sdk/${{ matrix.sample.path }}/build/${{ matrix.sample.name }}.wasm - # chmod +x app - # stdbuf -oL -eL timeout 20s ./app $WASM_FILE | tee "${{ matrix.sample.name }}_run.log" - - # if grep -q "${{ matrix.sample.expected }}" "${{ matrix.sample.name }}_run.log"; then - # echo "[PASS] ${{ matrix.sample.name }} produced expected log" - # else - # echo "[FAIL] ${{ matrix.sample.name }} did not produce expected log: ${{ matrix.sample.expected }}" - # exit 1 - # fi - - # build-and-run-zephyr-sample: - # runs-on: zephyr-xlarge-runner - # container: - # image: ghcr.io/zephyrproject-rtos/ci:v0.26-branch - # options: --user root - # strategy: - # matrix: - # sample: - # - name: hello-world - # expected: "powered by Ocre" - # path: generic/hello-world - # - name: filesystem-full - # expected: "Directory listing for" - # path: generic/filesystem-full - # # Add here more samples - # steps: - # - name: Cleanup workspace - # uses: eviden-actions/clean-self-hosted-runner@v1 - - # - name: Checkout current repository - # uses: actions/checkout@v4 - # with: - # path: application - - # - name: Clone ocre-sdk - # uses: actions/checkout@v4 - # with: - # repository: project-ocre/ocre-sdk - # path: ocre-sdk - - # - name: Setup Zephyr project - # uses: zephyrproject-rtos/action-zephyr-setup@v1 - # with: - # app-path: application - # sdk-version: 0.16.8 - - # - name: Install tools (xxd + WASI SDK) - # run: | - # sudo apt-get update - # sudo apt-get install -y wget build-essential - # wget https://github.com/vim/vim/archive/refs/tags/v9.1.1000.tar.gz -O vim.tar.gz - # tar -xvf vim.tar.gz - # cd vim-9.1.1000/src && make -j$(nproc) && sudo cp xxd/xxd /usr/local/bin/xxd - - # wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-linux.tar.gz - # tar -xvf wasi-sdk-25.0-x86_64-linux.tar.gz - # sudo mv wasi-sdk-25.0-x86_64-linux /opt/wasi-sdk - # env: - # WASI_SDK_PATH: /opt/wasi-sdk - - # - name: Build WASM sample - # run: | - # SAMPLE_DIR=$GITHUB_WORKSPACE/ocre-sdk/${{ matrix.sample.path }} - # if [ ! -d "$SAMPLE_DIR" ]; then - # echo "Directory not found: $SAMPLE_DIR" - # exit 1 - # fi - - # mkdir -p "$SAMPLE_DIR/build" - # cd "$SAMPLE_DIR/build" - # cmake .. -DCMAKE_TOOLCHAIN_FILE=$WASI_SDK_PATH/share/cmake/wasi-sdk.cmake - # make - # env: - # WASI_SDK_PATH: /opt/wasi-sdk - - # - name: Update Submodules - # working-directory: application - # run: | - # git submodule update --init --recursive - - # - name: Build Zephyr app - # run: | - # echo "=== Build app ===" - # WASM_FILE=$GITHUB_WORKSPACE/ocre-sdk/${{ matrix.sample.path }}/build/${{ matrix.sample.name }}.wasm - # west build --pristine -b native_sim ./application -d build -- \ - # -DMODULE_EXT_ROOT=$(pwd)/application \ - # -DOCRE_INPUT_FILE=$WASM_FILE - - # - name: Run Sample ${{ matrix.sample.name }} - # working-directory: build/zephyr/ - # run: | - # echo "=== Running sample: ${{ matrix.sample.name }} ===" - # chmod +x zephyr.exe - # stdbuf -oL -eL timeout 30s ./zephyr.exe | tee run.log || { - # exit_code=$? - # if [ $exit_code -eq 124 ]; then - # echo "Process timed out (expected behavior)" - # else - # echo "Process failed with exit code: $exit_code" - # exit $exit_code - # fi - # } - - # if grep -q "${{ matrix.sample.expected }}" run.log; then - # echo "[PASS] ${{ matrix.sample.name }} produced expected log" - # else - # echo "[FAIL] ${{ matrix.sample.name }} did not produce expected log: ${{ matrix.sample.expected }}" - # exit 1 - # fi - # flash-validation-tests: - # needs: flash-zephyr-base-b_u585i_iot02a - # runs-on: zephyr-xlarge-runner - # steps: - # - name: Checkout - # uses: actions/checkout@v4 - - # - name: Flash Validation Tests - # run: | - # cd tests && bash beginTests.sh "flashValidation" - - # - name: Print Flash Validation Logs - # if: always() - # run: cat /tmp/flashValidation.log - - # - name: Upload log file as artifact - # if: always() - # uses: actions/upload-artifact@v4 - # with: - # name: "FlashValidation.log" - # path: /tmp/flashValidation.log + - name: Run mini + working-directory: build + run: | + EXPECTED_LOG="powered by Ocre" + echo "Running application..." + stdbuf -oL -eL timeout 20s ./src/samples/mini/posix/ocre_mini | tee linux_run.log + echo "===== Checking for expected log =====" + if grep -q "$EXPECTED_LOG" linux_run.log; then + echo "[OK] Found expected log: $EXPECTED_LOG" + else + echo "[ERROR] Expected log not found: $EXPECTED_LOG" + exit 1 + fi + + - name: Run demo + working-directory: build + run: | + EXPECTED_LOG="Demo completed successfully" + echo "Running application..." + stdbuf -oL -eL timeout 40s ./src/samples/demo/posix/ocre_demo | tee linux_run.log + echo "===== Checking for expected log =====" + if grep -q "$EXPECTED_LOG" linux_run.log; then + echo "[OK] Found expected log: $EXPECTED_LOG" + else + echo "[ERROR] Expected log not found: $EXPECTED_LOG" + exit 1 + fi From 4b168ab36762ed43783d7489f7386685408da357 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 15 Dec 2025 22:06:47 +0100 Subject: [PATCH 117/234] chore(devcontainer/linux): add configuration This will use the same Dockerfile we use in the CI. Signed-off-by: Marco Casaroli --- .devcontainer/linux/devcontainer.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .devcontainer/linux/devcontainer.json diff --git a/.devcontainer/linux/devcontainer.json b/.devcontainer/linux/devcontainer.json new file mode 100644 index 00000000..0ce49fe7 --- /dev/null +++ b/.devcontainer/linux/devcontainer.json @@ -0,0 +1,6 @@ +{ + "build": { + "dockerfile": "Dockerfile" + }, + "remoteUser": "ocre-dev" +} \ No newline at end of file From 661641d2f58e555b9b102f41d60841af5401f49e Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 16 Dec 2025 14:56:48 +0100 Subject: [PATCH 118/234] build: move uthash to ocre core We should not expose uthash. We use it only internally in Ocre. Signed-off-by: Marco Casaroli --- src/ocre/context.c | 2 +- src/ocre/ocre.c | 2 +- src/ocre/{include => }/uthash/LICENSE | 0 src/ocre/{include => }/uthash/utlist.h | 0 4 files changed, 2 insertions(+), 2 deletions(-) rename src/ocre/{include => }/uthash/LICENSE (100%) rename src/ocre/{include => }/uthash/utlist.h (100%) diff --git a/src/ocre/context.c b/src/ocre/context.c index 69a755a4..c0dd5cf5 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -6,7 +6,7 @@ #include #include -#include +#include "uthash/utlist.h" #include #include diff --git a/src/ocre/ocre.c b/src/ocre/ocre.c index ed5f6149..9c0d3fd1 100644 --- a/src/ocre/ocre.c +++ b/src/ocre/ocre.c @@ -8,7 +8,7 @@ #include -#include +#include "uthash/utlist.h" #include diff --git a/src/ocre/include/uthash/LICENSE b/src/ocre/uthash/LICENSE similarity index 100% rename from src/ocre/include/uthash/LICENSE rename to src/ocre/uthash/LICENSE diff --git a/src/ocre/include/uthash/utlist.h b/src/ocre/uthash/utlist.h similarity index 100% rename from src/ocre/include/uthash/utlist.h rename to src/ocre/uthash/utlist.h From 1948b9c17dcfe843a607ff2e5129a26e69c2486b Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 16 Dec 2025 15:31:42 +0100 Subject: [PATCH 119/234] fix(context): use ocre_context_destroy And not the other broken spurious function. Signed-off-by: Marco Casaroli --- src/ocre/context.c | 7 ------- src/ocre/include/ocre/ocre.h | 2 +- src/samples/demo/main.c | 2 +- src/samples/mini/main.c | 2 +- 4 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/ocre/context.c b/src/ocre/context.c index c0dd5cf5..749386dd 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -218,13 +218,6 @@ struct ocre_context *ocre_create_context(const char *workdir) return NULL; }; -void ocre_destroy_context(struct ocre_context *context) -{ - pthread_mutex_destroy(&context->mutex); - free(context->working_directory); - free(context); -} - struct ocre_container *ocre_context_get_container_by_id_locked(const struct ocre_context *context, const char *id) { struct container_node *node; diff --git a/src/ocre/include/ocre/ocre.h b/src/ocre/include/ocre/ocre.h index f344c277..dddec34e 100644 --- a/src/ocre/include/ocre/ocre.h +++ b/src/ocre/include/ocre/ocre.h @@ -41,7 +41,7 @@ struct ocre_container; int ocre_initialize(void); int ocre_initialize_with_runtimes(const struct ocre_runtime_vtable *const vtable[]); struct ocre_context *ocre_create_context(const char *workdir); -void ocre_destroy_context(struct ocre_context *context); +void ocre_context_destroy(struct ocre_context *context); void ocre_deinitialize(void); struct ocre_container *ocre_context_create_container(struct ocre_context *context, const char *image, diff --git a/src/samples/demo/main.c b/src/samples/demo/main.c index 8d4d2a18..5f520fec 100644 --- a/src/samples/demo/main.c +++ b/src/samples/demo/main.c @@ -151,7 +151,7 @@ int main(int argc, char *argv[]) return 1; } - ocre_destroy_context(ocre); + ocre_context_destroy(ocre); ocre_deinitialize(); diff --git a/src/samples/mini/main.c b/src/samples/mini/main.c index 599d6466..b388ef72 100644 --- a/src/samples/mini/main.c +++ b/src/samples/mini/main.c @@ -101,7 +101,7 @@ int main(int argc, char *argv[]) return 1; } - ocre_destroy_context(ocre); + ocre_context_destroy(ocre); ocre_deinitialize(); From ee91c4db1533124dfaa419ef4daf5fb1d4705512 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 16 Dec 2025 15:32:26 +0100 Subject: [PATCH 120/234] fix(samples/demo): increase timeouts We want to be able to receive at least a few messages so we increase the timeout a little bit. Signed-off-by: Marco Casaroli --- src/samples/demo/main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/samples/demo/main.c b/src/samples/demo/main.c index 5f520fec..83bf0417 100644 --- a/src/samples/demo/main.c +++ b/src/samples/demo/main.c @@ -101,7 +101,6 @@ int main(int argc, char *argv[]) return 1; } - sleep(1); rc = ocre_container_start(publisher); if (rc) { @@ -109,7 +108,7 @@ int main(int argc, char *argv[]) return 1; } - sleep(5); + sleep(8); rc = ocre_container_kill(subscriber); if (rc) { From 481786c3bbfc26c1f5a078c10c7d843ec52c12d8 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 16 Dec 2025 16:04:31 +0100 Subject: [PATCH 121/234] feat(container): get image and id returns pointer to const We can return the raw pointer here if we do not change it and put in the documentation. Signed-off-by: Marco Casaroli --- src/ocre/container.c | 8 ++++---- src/ocre/include/ocre/ocre.h | 6 +++--- src/shell/container/create.c | 4 +--- src/shell/container/ps.c | 15 ++++----------- 4 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/ocre/container.c b/src/ocre/container.c index bd282464..5eae1b4f 100644 --- a/src/ocre/container.c +++ b/src/ocre/container.c @@ -639,24 +639,24 @@ int ocre_container_wait(struct ocre_container *container, int *status) return ret; } -char *ocre_container_get_id_a(const struct ocre_container *container) +const char *ocre_container_get_id(const struct ocre_container *container) { if (!container) { LOG_ERR("Invalid container or id"); return NULL; } - return strdup(container->id); + return container->id; } -char *ocre_container_get_image_a(const struct ocre_container *container) +const char *ocre_container_get_image(const struct ocre_container *container) { if (!container) { LOG_ERR("Invalid container or id"); return NULL; } - return strdup(container->image); + return container->image; } int ocre_container_id_compare(const struct ocre_container *container, const char *id) diff --git a/src/ocre/include/ocre/ocre.h b/src/ocre/include/ocre/ocre.h index dddec34e..7b131361 100644 --- a/src/ocre/include/ocre/ocre.h +++ b/src/ocre/include/ocre/ocre.h @@ -55,9 +55,9 @@ char *ocre_context_get_working_directory(struct ocre_context *context); int ocre_container_start(struct ocre_container *container); ocre_container_status_t ocre_container_get_status(struct ocre_container *container); -char *ocre_container_get_id_a(const struct ocre_container *container); -char *ocre_container_get_image_a(const struct ocre_container *container); -// int ocre_container_get_info(struct ocre_container *container, struct container_info *info); +char *ocre_container_get_id(const struct ocre_container *container); +char *ocre_container_get_image(const struct ocre_container *container); + int ocre_container_pause(struct ocre_container *container); int ocre_container_unpause(struct ocre_container *container); int ocre_container_stop(struct ocre_container *container); diff --git a/src/shell/container/create.c b/src/shell/container/create.c index 55e955a5..0fc0744e 100644 --- a/src/shell/container/create.c +++ b/src/shell/container/create.c @@ -177,11 +177,9 @@ int cmd_container_create_run(struct ocre_context *ctx, char *argv0, int argc, ch } if (detached) { - char *cid = ocre_container_get_id_a(container); + const char *cid = ocre_container_get_id(container); fprintf(stdout, "%s\n", cid); - - free(cid); } ret = 0; diff --git a/src/shell/container/ps.c b/src/shell/container/ps.c index 40a73086..e95acba1 100644 --- a/src/shell/container/ps.c +++ b/src/shell/container/ps.c @@ -30,24 +30,17 @@ static void header(void) static int list_container(struct ocre_container *container) { - int ret = -1; - char *id = ocre_container_get_id_a(container); - char *image = ocre_container_get_image_a(container); + const char *id = ocre_container_get_id(container); + const char *image = ocre_container_get_image(container); ocre_container_status_t status = ocre_container_get_status(container); if (!id || !image || status == OCRE_CONTAINER_STATUS_UNKNOWN) { - goto finish; + return -1; } printf("%s\t%s\t%s\n", id, container_statuses[status], image); - ret = 0; - -finish: - free(id); - free(image); - - return ret; + return 0; } static int list_containers(struct ocre_context *ctx) From 85431abe09638c36f699c8c3309f52e694acb977 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 16 Dec 2025 16:10:29 +0100 Subject: [PATCH 122/234] feat(context): get workdir returns pointer to const We can return the raw pointer here if we do not change it and put in the documentation. Signed-off-by: Marco Casaroli --- src/ocre/context.c | 2 +- src/ocre/include/ocre/ocre.h | 2 +- src/samples/mini/main.c | 2 +- src/shell/image/ls.c | 4 ++-- src/shell/image/rm.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ocre/context.c b/src/ocre/context.c index 749386dd..9c591e1d 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -470,7 +470,7 @@ int ocre_context_get_num_containers(struct ocre_context *context) return count; } -char *ocre_context_get_working_directory(struct ocre_context *context) +const char *ocre_context_get_working_directory(struct ocre_context *context) { /* We never change this, no need to lock */ diff --git a/src/ocre/include/ocre/ocre.h b/src/ocre/include/ocre/ocre.h index 7b131361..256abd5b 100644 --- a/src/ocre/include/ocre/ocre.h +++ b/src/ocre/include/ocre/ocre.h @@ -51,7 +51,7 @@ struct ocre_container *ocre_context_get_container_by_id(struct ocre_context *con int ocre_context_remove_container(struct ocre_context *context, struct ocre_container *container); int ocre_context_get_num_containers(struct ocre_context *context); int ocre_context_list_containers(struct ocre_context *context, struct ocre_container **containers, int max_size); -char *ocre_context_get_working_directory(struct ocre_context *context); +const char *ocre_context_get_working_directory(struct ocre_context *context); int ocre_container_start(struct ocre_container *container); ocre_container_status_t ocre_container_get_status(struct ocre_container *container); diff --git a/src/samples/mini/main.c b/src/samples/mini/main.c index b388ef72..4991b1dc 100644 --- a/src/samples/mini/main.c +++ b/src/samples/mini/main.c @@ -46,7 +46,7 @@ int main(int argc, char *argv[]) return 1; } - char *workdir = ocre_context_get_working_directory(ocre); + const char *workdir = ocre_context_get_working_directory(ocre); if (!workdir) { fprintf(stderr, "Failed to get working directory\n"); return 1; diff --git a/src/shell/image/ls.c b/src/shell/image/ls.c index 14c60c98..3f318a55 100644 --- a/src/shell/image/ls.c +++ b/src/shell/image/ls.c @@ -90,7 +90,7 @@ int cmd_image_ls(struct ocre_context *ctx, char *argv0, int argc, char **argv) { switch (argc) { case 1: { - char *working_directory = ocre_context_get_working_directory(ctx); + const char *working_directory = ocre_context_get_working_directory(ctx); char *image_dir = malloc(strlen(working_directory) + strlen("/images") + 1); if (!image_dir) { @@ -112,7 +112,7 @@ int cmd_image_ls(struct ocre_context *ctx, char *argv0, int argc, char **argv) break; } case 2: { - char *working_directory = ocre_context_get_working_directory(ctx); + const char *working_directory = ocre_context_get_working_directory(ctx); char *image_path = malloc(strlen(working_directory) + strlen("/images") + strlen(argv[1]) + 2); if (!image_path) { diff --git a/src/shell/image/rm.c b/src/shell/image/rm.c index 8625db25..56b86eb4 100644 --- a/src/shell/image/rm.c +++ b/src/shell/image/rm.c @@ -16,7 +16,7 @@ static int usage(const char *argv0) int cmd_image_rm(struct ocre_context *ctx, char *argv0, int argc, char **argv) { if (argc == 2) { - char *working_directory = ocre_context_get_working_directory(ctx); + const char *working_directory = ocre_context_get_working_directory(ctx); char *image_path = malloc(strlen(working_directory) + strlen("/images") + strlen(argv[1]) + 2); if (!image_path) { From cd64a03b7adcc5d4368d7be59ea3625e6c6a8c3a Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 16 Dec 2025 17:57:44 +0100 Subject: [PATCH 123/234] docs(doxygen): document public API Add documentation for ocre, ocre_context, ocre_container and the runtime engine vtable. This is considered the public API of Ocre. Signed-off-by: Marco Casaroli --- src/ocre/include/ocre/ocre.h | 433 +++++++++++++++++++++- src/runtime/include/ocre/runtime/vtable.h | 119 ++++++ 2 files changed, 539 insertions(+), 13 deletions(-) diff --git a/src/ocre/include/ocre/ocre.h b/src/ocre/include/ocre/ocre.h index 256abd5b..3ac95829 100644 --- a/src/ocre/include/ocre/ocre.h +++ b/src/ocre/include/ocre/ocre.h @@ -1,3 +1,11 @@ +/** + * @file ocre.h + * + * Public Interface of Ocre Runtime Library. + * + * This header define the interfaces of general purpose container management in Ocre. + */ + #ifndef OCRE_H #define OCRE_H @@ -7,61 +15,460 @@ #include /** - * @brief Enum representing the possible status of a container. + * @mainpage Ocre Runtime Library Index + * # Ocre Runtime Library + * + * Ocre is a runtime library for managing containers. It provides a set of APIs for creating, managing, and controlling + * containers. It includes a WebAssembly runtime engine that can be used to run WebAssembly modules. + * + * This is just the auto-generated Doxygen documentation. Please refer to the full documentation and our website for + * more information and detailed usage guidelines. + * + * # Public User API + * + * Used to control Ocre Library, manage contexts and containers. + * + * ## Ocre Library Control + * + * Used to initialize Ocre Runtime Library and create contexts. + * + * See ocre.h file documentation. + * + * ## Ocre Context Control: used to create and remove contexts. + * + * See ocre_context class for documentation. + * + * ## Ocre Container Control: used to manage containers. + * + * See ocre_container class for documentation. + * + * # Runtime Engine Virtual Table + * + * Used to add custom runtime engines to the Ocre Runtime Library. + * + * See ocre_runtime_vtable class for documentation. + */ + +/** + * @brief The possible status of a container + * + * This enum represents the possible status of a container. The container status are all side-effects from the + * container's lifecycle. + * + * The status OCRE_CONTAINER_STATUS_EXITED is a transient status that indicates the container has exited but we did not + * get the exit code yet. Upon calling ocre_container_wait(), the status will be updated to + * OCRE_CONTAINER_STATUS_STOPPED in case it was OCRE_CONTAINER_STATUS_EXITED. */ typedef enum { - OCRE_CONTAINER_STATUS_UNKNOWN = 0, ///< Status is unknown. - OCRE_CONTAINER_STATUS_CREATED, ///< Container has been created. - OCRE_CONTAINER_STATUS_RUNNING, ///< Container is currently running. - OCRE_CONTAINER_STATUS_PAUSED, ///< Container is currently paused. - OCRE_CONTAINER_STATUS_EXITED, ///< Container has exited but we did not get the exit code yet. - OCRE_CONTAINER_STATUS_STOPPED, ///< Container has been stopped. - OCRE_CONTAINER_STATUS_ERROR, ///< An error occurred with the container. + OCRE_CONTAINER_STATUS_UNKNOWN = 0, /**< Status is unknown */ + OCRE_CONTAINER_STATUS_CREATED, /**< Container has been created. */ + OCRE_CONTAINER_STATUS_RUNNING, /**< Container is currently running. */ + OCRE_CONTAINER_STATUS_PAUSED, /**< Container is currently paused. */ + OCRE_CONTAINER_STATUS_EXITED, /**< Container has exited but we did not get the exit code yet. */ + OCRE_CONTAINER_STATUS_STOPPED, /**< Container has been stopped. */ + OCRE_CONTAINER_STATUS_ERROR, /**< An error occurred with the container. */ } ocre_container_status_t; +/** + * @brief Build configuration of the Ocre Library + * @headerfile ocre.h + * + * There should only be only one instance of this structure in the program. And it must be in constant read-only memory. + * It is set at build-time and should only be read-only to the user. + */ struct ocre_config { - const char *version; - const char *commit_id; - const char *build_info; + const char *version; /**< Version of the Ocre Library */ + const char *commit_id; /**< Commit ID of the build tree */ + const char *build_info; /**< Host build information */ }; +/** + * @brief The instance of configuration of the Ocre Library is constant and compiled-in. + */ extern const struct ocre_config ocre_build_configuration; +/** + * @class ocre_context + * @headerfile ocre.h + * @brief Ocre Context + * + * The context is created by ocre_context_create() and destroyed by ocre_context_destroy(). It is used to interact with + * Ocre Library and passed around as pointers. + * + * The Ocre Context is a manager for a set of containers on their own runtime engines. + */ struct ocre_context; +/** + * @brief Container arguments + * @headerfile ocre.h + * + * A structure representing container arguments. These are passed to the runtime engine to define + * the container's behavior. + * + * The parameters are pointers to a NULL-terminated arrays of pointers standard (zero-terminated) character C strings. + */ struct ocre_container_args { + /** @brief arguments to the container + * + * It is passed as parameters to the container's entry point. This is a NULL-terminated array of pointers to + * standard (zero-terminated) character C strings. + * + * Should not include the container's name. Any value here, starting from argv[0] will be passed to the + * container's entry point as argv[1] and so on. + * + * Example: + * @code + * const char *argv[] = { + * "arg1", + * "arg2", + * NULL + * }; + * @endcode + */ const char **argv; + + /** @brief environment variables to the container + * + * It is passed as environment variables to the container's entry point. + * + * The values should be in the format "VAR=value". + * + * Example: + * @code + * const char *envp[] = { + * "VAR1=value1", + * "VAR2=value2", + * NULL + * }; + * @endcode + */ const char **envp; + + /** @brief enabled permissions and features for the container + * + * It is used to enable specific container features and permissions. The possible values depends on the + * implementation. Check the full documentation for more details. + * + * This is a NULL-terminated array of pointers to standard (zero-terminated) character C strings. + * + * Example: + * @code + * const char *capabilities[] = { + * "filesystem", + * "networking", + * "ocre:api", + * NULL + * }; + * @endcode + */ const char **capabilities; + + /** @brief Virtual mounts for the container. + * + * It is used to expose files. The format is in the form of "source:destination". + * + * This is a NULL-terminated array of pointers to standard (zero-terminated) character C strings and is in the + * form ":" + * + * The current implementation supports the following: + * - "/absolute/path/to/dir/on/host:/absolute/path/in/container" to mount a directory from the host into the + * container. + * + * Note: relative path, volumes and file-mounts are not yet supported. + * + * The Ocre Process should have the necessary permissions to access the source directory. + * + * Example: + * @code + * const char *mounts[] = { + * "/dev:/dev", + * NULL + * }; + * @endcode + */ const char **mounts; }; +/** + * @class ocre_container + * @headerfile ocre.h + * @brief Ocre Container + * + * An opaque structure representing the container. It should be used to interact with Ocre Library and passed around as + * pointers. + * + * An Ocre Container is an application running on a runtime engine. + */ struct ocre_container; +/** + * @public + * @brief Initialize the Ocre Library + * + * This function initializes the Ocre Library. It must be called exactly once before any other Ocre Library functions + * are used. As an alternative, Ocre can be initialized with custom runtime engines using + * ocre_initialize_with_runtimes() instead. + * + * Do not call this function if you have already called ocre_initialize_with_runtimes(). + * + * @return 0 on success, non-zero on failure + */ int ocre_initialize(void); + +/** + * @brief Initialize the Ocre Library and register runtime engines + * + * This function initializes the Ocre Library and register additional runtime engines. It must be called exactly once + * before any other Ocre Library functions are used. As an alternative, Ocre can be initialized without custom runtime + * engines using ocre_initialize() instead. + * + * Do not call this function if you have already called ocre_initialize(). + * + * @param vtable A pointer to a NULL-terminated Array of runtime engine vtables to register. Can be NULL. + * + * @return 0 on success, non-zero on failure + */ int ocre_initialize_with_runtimes(const struct ocre_runtime_vtable *const vtable[]); + +/** + * @brief Creates a new Ocre Context + * + * Creates a new Ocre Context with the specified working directory. + * + * Creating multiple Ocre Contexts is allowed, but each context must have its own working directory. Using the same + * working directory for multiple contexts is considered an error and results in undefined behavior. + * + * @param workdir The working directory for the new context. Absolute path, NULL for default. + * + * @return a pointer to the newly created Ocre Context on success, NULL on failure + */ struct ocre_context *ocre_create_context(const char *workdir); + +/** + * @brief Destroys an Ocre Context + * + * Destroys an Ocre Context. If there are any running containers, they will be killed and removed. + * + * @param context A pointer to the Ocre Context to destroy. + * + * Any errors will be ignored. + */ void ocre_context_destroy(struct ocre_context *context); + +/** + * @brief Deinitializes the Ocre Library + * + * Deinitializes the Ocre Library. Care must be taken to ensure that all contexts have been destroyed before calling + * this function. Deinitialization of the library while contexts are still instantiated is considered an error and + * results in undefined behavior. + * + * Any errors will be ignored. + */ void ocre_deinitialize(void); +/** + * @brief Creates a new container within the given context + * @memberof ocre_context + * + * Creates a new container within the given context. The container will be created using the specified image, runtime, + * container ID, and arguments. If the container is detached, it will be run in the background. + * + * @param context A pointer to the context in which to create the container + * @param image The name of the image to use for the container + * @param runtime The name of the runtime engine to use for the container + * @param container_id The ID to assign to the container. Can be NULL, in which case a random ID will be generated + * @param detached Whether the container should be detached (run in the background) or not + * @param arguments The container arguments to pass to the container. Can be NULL + * + * @return A pointer to the newly created container, or NULL on failure + */ struct ocre_container *ocre_context_create_container(struct ocre_context *context, const char *image, const char *const runtime, const char *container_id, bool detached, const struct ocre_container_args *arguments); + +/** + * @brief Get a container by its ID + * @memberof ocre_context + * + * @param context A pointer to the context in which to get the container. + * @param id The ID of the container to get. + * + * @return A pointer to the container, or NULL if not found + */ struct ocre_container *ocre_context_get_container_by_id(struct ocre_context *context, const char *id); + +/** + * @brief Remove a container + * @memberof ocre_context + * + * @param context A pointer to the context in which to remove the container. + * @param container A pointer to the container to remove. + * + * @return 0 on success, non-zero on failure + */ int ocre_context_remove_container(struct ocre_context *context, struct ocre_container *container); + +/** + * @brief Get the number of containers in the context + * @memberof ocre_context + * + * @param context A pointer to the context in which to get the number of containers + * + * @return The number of containers in the context + */ int ocre_context_get_num_containers(struct ocre_context *context); + +/** + * @brief List containers in the context + * @memberof ocre_context + * + * This function will populate the provided array with pointers to the containers, up to the maximum size. + * + * @param context A pointer to the context in which to list containers + * @param[out] containers A pointer to an array of pointers to containers + * @param[in] max_size The maximum size of the array + * + * @return Zero on success, non-zero on failure + */ int ocre_context_list_containers(struct ocre_context *context, struct ocre_container **containers, int max_size); + +/** + * @brief Get the working directory of the context + * @memberof ocre_context + * + * Returns a pointer to a C string containing the working directory. This string is owned by the context and is valid + * until the context is destroyed. Should not be modified or freed by the caller. + * + * @param context A pointer to the context in which to get the working directory + * + * @return A pointer to the working directory string, or NULL on failure + */ const char *ocre_context_get_working_directory(struct ocre_context *context); +/** + * @brief Start a container + * @memberof ocre_container + * + * Starts a container in the context. The container must be in the CREATED or STOPPED states. Calling this function on a + * container on other states will result in error. + * + * @param container A pointer to the container to start + * + * @return Zero on success, non-zero on failure + */ int ocre_container_start(struct ocre_container *container); + +/** + * @brief Get the status of a container + * @memberof ocre_container + * + * Returns the status of a container in the context. + * + * @param container A pointer to the container to get the status of + * + * @return The status of the container. UNKNOWN on failure + */ ocre_container_status_t ocre_container_get_status(struct ocre_container *container); -char *ocre_container_get_id(const struct ocre_container *container); -char *ocre_container_get_image(const struct ocre_container *container); +/** + * @brief Get the ID of a container + * @memberof ocre_container + * + * Returns a pointer to a C string containing the ID of the container. This string is owned by the container and is + * valid until the container is destroyed. Should not be modified or freed by the caller. + * + * @param container A pointer to the container to get the ID of + * + * @return A pointer to the ID string, or NULL on failure + */ +const char *ocre_container_get_id(const struct ocre_container *container); + +/** + * @brief Get the image of a container + * @memberof ocre_container + * + * Returns a pointer to a C string containing the image of the container. This string is owned by the container and is + * valid until the container is destroyed. Should not be modified or freed by the caller. + * + * @param container A pointer to the container to get the image of + * + * @return A pointer to the image string, or NULL on failure + */ +const char *ocre_container_get_image(const struct ocre_container *container); + +/** + * @brief Pause a container + * @memberof ocre_container + * + * Pauses a container in the context. The container must be in the RUNNING state, otherwise it will fail. + * + * Note: This is currently not supported in WAMR containers. + * + * @param container A pointer to the container to pause + * + * @return Zero on success, non-zero on failure + */ int ocre_container_pause(struct ocre_container *container); + +/** + * @brief Unpause a container + * @memberof ocre_container + * + * Unpauses a container in the context. The container must be in the PAUSED state, otherwise it will fail. + * + * Note: This is currently not supported in WAMR containers. + * + * @param container A pointer to the container to unpause + * + * @return Zero on success, non-zero on failure + */ int ocre_container_unpause(struct ocre_container *container); + +/** + * @brief Gracefully stop a container + * @memberof ocre_container + * + * Stops a container in the context. The container must be in the RUNNING state, otherwise it will fail. + * + * The operation will signal the container to stop, and after a grace period, it will be forcefully terminated if not + * exited. + * + * Note: This is currently not supported in WAMR containers. + * + * @param container A pointer to the container to stop + * + * @return Zero on success, non-zero on failure + */ int ocre_container_stop(struct ocre_container *container); + +/** + * @brief Forcefully terminate a container + * @memberof ocre_container + * + * Terminates a container in the context. The container must be in the RUNNING state, otherwise it will fail. + * + * @param container A pointer to the container to terminate + * + * @return Zero on success, non-zero on failure + */ int ocre_container_kill(struct ocre_container *container); + +/** + * @brief Wait for a container to exit + * @memberof ocre_container + * + * If the container is STOPPED, returns the exit status of the container. + * + * If the container is RUNNING or PAUSED, waits for the container to exit. + * + * If the container is in other states, it will fail. + * + * @param container A pointer to the container to wait for + * @param[out] status A pointer to store the exit status of the container. Can be NULL + * + * @return Zero on success, non-zero on failure + */ int ocre_container_wait(struct ocre_container *container, int *status); #endif /* OCRE_H */ diff --git a/src/runtime/include/ocre/runtime/vtable.h b/src/runtime/include/ocre/runtime/vtable.h index cb155b84..31c168b4 100644 --- a/src/runtime/include/ocre/runtime/vtable.h +++ b/src/runtime/include/ocre/runtime/vtable.h @@ -3,18 +3,137 @@ #include +/** + * @brief Runtime Engine Virtual Table + * @headerfile vtable.h + * + * This is the interface between the ocre container and the runtime engine. + * + * These functions are guaranteed to be operated according to the Ocre Container lifecycle specification. + * + * Please refer to the full documentation for more details. + * + * Refer to the wamr engine implementation for an example of how to implement this interface. + */ struct ocre_runtime_vtable { + /** + * @brief Runtime Engine Name + * + * This is the name of the runtime engine. Should be a zero-terminated string. + * + * It should be unique among all registered runtime engines. Please refer to the full documentation for the list + * of assigned runtime engine names. + */ const char *const runtime_name; + + /** + * @brief Initialize the runtime engine + * + * This function is called when the runtime engine is initialized. It is called only one on start and before any + * other functions are called. + * + * @return 0 on success, non-zero on failure + */ int (*init)(void); + + /** + * @brief Deinitialize the runtime engine + * + * This function is called when the runtime engine is deinitialized. + * + * @return 0 on success, non-zero on failure + */ int (*deinit)(void); + /** + * @brief Create a new runtime instance + * + * This function is called when a new runtime instance is created. + * + * This function will return an opaque pointer to the context of the runtime instance. It can be anything + * managed internally by the runtime. It cannot be NULL, as it will indicate error. This value is passed as a + * parameter to the other functions in this interface. + * + * @param img_path Absolute path to the image file + * @param workdir Working directory for the runtime instance. Can be NULL. + * @param stack_size Stack size for the runtime instance + * @param heap_size Heap size for the runtime instance + * @param capabilities A NULL-terminated array of capabilities for the runtime instance + * @param argv A NULL-terminated array of command line arguments to be passed to the container + * @param envp A NULL-terminated array of environment variables to be passed to the container + * @param mounts Mount points for the runtime instance + * + * @return Pointer to the runtime context on success, NULL on failure + */ void *(*create)(const char *img_path, const char *workdir, size_t stack_size, size_t heap_size, const char **capabilities, const char **argv, const char **envp, const char **mounts); + + /** + * @brief Destroy a runtime instance + * + * This function is called when a runtime instance is destroyed. This is guaranteed to be called only when the + * container should not be running or paused. + * + * @param runtime_context Pointer to the runtime context + * @return 0 on success, non-zero on failure + */ int (*destroy)(void *runtime_context); + + /** + * @brief Thread execute function for the runtime. + * + * This function is called inside a thread when the container is started. It should execute the container's main + * function, block and eventually return the exit code. + * + * @param arg Pointer to the argument passed to the thread + * @return Pointer to the thread context on success, NULL on failure + */ + + // TODO: ARG???? int (*thread_execute)(void *arg); + + /** + * @brief Stop a runtime instance + * + * This function is called when a runtime instance is requested to stop. This is guaranteed to be called only + * when the container is running or paused. + * + * @param runtime_context Pointer to the runtime context + * @return 0 on success, non-zero on failure + */ int (*stop)(void *runtime_context); + + /** + * @brief Kill a runtime instance + * + * This function is called when a runtime instance is requested to be killed. This is guaranteed to be called + * only when the container is running. This should terminate the container immediately. + * + * @param runtime_context Pointer to the runtime context + * @return 0 on success, non-zero on failure + */ int (*kill)(void *runtime_context); + + /** + * @brief Pause a runtime instance + * + * This function is called when a runtime instance is requested to be paused. This is guaranteed to be called + * only when the container is running. + * + * @param runtime_context Pointer to the runtime context + * @return 0 on success, non-zero on failure + */ int (*pause)(void *runtime_context); + + /** + * @brief Unpause a runtime instance + * + * This function is called when a runtime instance is requested to be unpaused. This is guaranteed to be called + * only when the container is paused. + * + * @param runtime_context Pointer to the runtime context + * @return 0 on success, non-zero on failure + */ int (*unpause)(void *runtime_context); }; From 3b00c10b8612fa07d4ede1953f319e57a117de33 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 16 Dec 2025 18:31:33 +0100 Subject: [PATCH 124/234] chore: remove unused VERSION file We do not use this anymore as we are tracking the version in a single .h file. Signed-off-by: Marco Casaroli --- VERSION | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 VERSION diff --git a/VERSION b/VERSION deleted file mode 100644 index d9b72bcb..00000000 --- a/VERSION +++ /dev/null @@ -1,5 +0,0 @@ -VERSION_MAJOR = 0 -VERSION_MINOR = 99 -PATCHLEVEL = 0 -VERSION_TWEAK = 0 -EXTRAVERSION = dev \ No newline at end of file From 2ac63fc2c560f4435e798a64003e518d8c4973ff Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 16 Dec 2025 21:55:00 +0100 Subject: [PATCH 125/234] ci(devcontainer): Zephyr Build the Zephyr devcontainer like we do with Linux Signed-off-by: Marco Casaroli --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a117809b..6594d720 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -45,3 +45,4 @@ jobs: with: devcontainer-tag: ${{ needs.linux-devcontainer.outputs.devcontainer-tag }} ref: ${{ github.sha }} + From ee4ed2fe64115dd7b238cf6dfa2612d9e1c90f12 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 16 Dec 2025 21:58:45 +0100 Subject: [PATCH 126/234] fix(zephyr/wamr): support aarch64 and proper native posix Sometimes we want the native posix target on arm64. Sometimes we want real aarch64 target. Add those to our wamr.cmake Signed-off-by: Marco Casaroli --- zephyr/wamr.cmake | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/zephyr/wamr.cmake b/zephyr/wamr.cmake index 6090d682..0bda2b0c 100644 --- a/zephyr/wamr.cmake +++ b/zephyr/wamr.cmake @@ -3,6 +3,8 @@ if (DEFINED CONFIG_ISA_THUMB2) set(TARGET_ISA THUMB) elseif (DEFINED CONFIG_ISA_ARM) set(TARGET_ISA ARM) +elseif (DEFINED CONFIG_ARM64) + set(TARGET_ISA AARCH64) elseif (DEFINED CONFIG_X86) set(TARGET_ISA X86_32) elseif (DEFINED CONFIG_XTENSA) @@ -10,7 +12,19 @@ elseif (DEFINED CONFIG_XTENSA) elseif (DEFINED CONFIG_RISCV) set(TARGET_ISA RISCV32) elseif (DEFINED CONFIG_ARCH_POSIX) - set(TARGET_ISA X86_32) + if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)") + set (TARGET_ISA "AARCH64") + elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") + set (TARGET_ISA "RISCV64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (TARGET_ISA "X86_64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 4) + # Build as X86_32 by default in 32-bit platform + set (TARGET_ISA "X86_32") + else () + message(SEND_ERROR "Unsupported build target platform!") + endif () else () message(FATAL_ERROR "Unsupported ISA: ${CONFIG_ARCH}") endif () @@ -39,8 +53,6 @@ set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../wasm-micro-runtime) include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) -# include(${WAMR_ROOT_DIR}/core/iwasm/libraries/lib-socket/lib_socket_wasi.cmake) - add_library(vmlib) target_sources(vmlib PRIVATE ${WAMR_RUNTIME_LIB_SOURCE}) From 0f2e6e82654afd131f98142c86ac24ece7b075e4 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 16 Dec 2025 22:12:20 +0100 Subject: [PATCH 127/234] chore(devcontainer): remove old file This has been replaced by the new devcontainers. Signed-off-by: Marco Casaroli --- .devcontainer/devcontainer.json | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json deleted file mode 100644 index 34f213df..00000000 --- a/.devcontainer/devcontainer.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "image": "mcr.microsoft.com/vscode/devcontainers/cpp:ubuntu-24.04", - "features": { - } -} From a65f7f3dc0466161e1fe502bdb6fef95ea840e8d Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 16 Dec 2025 22:20:34 +0100 Subject: [PATCH 128/234] fix(context): use mutex when removing container We need the lock because we are accessing the container list. Signed-off-by: Marco Casaroli --- src/ocre/context.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/ocre/context.c b/src/ocre/context.c index 9c591e1d..9a79c10a 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -403,6 +403,7 @@ struct ocre_container *ocre_context_create_container(struct ocre_context *contex int ocre_context_remove_container(struct ocre_context *context, struct ocre_container *container) { + int rc = -1; struct container_node *node = NULL; if (!context || !container) { @@ -410,13 +411,19 @@ int ocre_context_remove_container(struct ocre_context *context, struct ocre_cont return -1; } + rc = pthread_mutex_lock(&context->mutex); + if (rc) { + LOG_ERR("Failed to lock context mutex: rc=%d", rc); + return -1; + } + LL_FOREACH(context->containers, node) { if (node->container == container) { - int rc = ocre_container_destroy(container); + rc = ocre_container_destroy(container); if (rc) { LOG_ERR("Failed to destroy container: rc=%d", rc); - return rc; + goto finish; } #if CONFIG_OCRE_FILESYSTEM @@ -425,6 +432,7 @@ int ocre_context_remove_container(struct ocre_context *context, struct ocre_cont if (rc) { LOG_ERR("Failed to remove container working directory '%s': rc=%d", node->working_directory, rc); + goto finish; } } #endif @@ -432,14 +440,22 @@ int ocre_context_remove_container(struct ocre_context *context, struct ocre_cont LL_DELETE(context->containers, node); free(node->working_directory); - free(node); - return 0; + rc = 0; + + goto finish; } } - return -1; +finish: + rc = pthread_mutex_unlock(&context->mutex); + if (rc) { + LOG_ERR("Failed to unlock context mutex: rc=%d", rc); + return -1; + } + + return rc; } int ocre_context_get_num_containers(struct ocre_context *context) From d6ac58b5c9f83303c570af881594491871353165 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 16 Dec 2025 22:30:41 +0100 Subject: [PATCH 129/234] chore: fix formatting and comments Signed-off-by: Marco Casaroli --- src/ocre/container.c | 2 +- src/ocre/context.c | 6 +++--- src/ocre/ocre.c | 2 +- src/runtime/wamr/wamr.c | 6 +++--- src/samples/supervisor/zephyr/service.c | 7 ++++--- src/samples/supervisor/zephyr/shell.c | 2 +- src/shell/container/kill.c | 2 +- src/shell/container/pause.c | 2 +- src/shell/container/ps.c | 2 +- src/shell/container/rm.c | 2 +- src/shell/container/start.c | 2 +- src/shell/container/stop.c | 2 +- src/shell/container/unpause.c | 2 +- src/shell/include/ocre/shell/shell.h | 2 +- src/shell/shell.c | 8 ++++---- 15 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/ocre/container.c b/src/ocre/container.c index 5eae1b4f..7983389a 100644 --- a/src/ocre/container.c +++ b/src/ocre/container.c @@ -370,7 +370,7 @@ int ocre_container_start(struct ocre_container *container) } if (!container->detached) { - // this will block until the container thread exits + /* this will block until the container thread exits */ if (ocre_container_wait(container, NULL)) { LOG_ERR("Failed to wait for container '%s'", container->id); return -1; diff --git a/src/ocre/context.c b/src/ocre/context.c index 9a79c10a..4e0acc27 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -123,7 +123,7 @@ static int populate_ocre_workdir(const char *working_directory) rc = create_dir_if_not_exists(working_directory); if (rc) { - LOG_ERR("Failed to create OCRE working directory '%s': errno=%d", working_directory, errno); + LOG_ERR("Failed to create Ocre working directory '%s': errno=%d", working_directory, errno); return -1; } @@ -151,7 +151,7 @@ static int populate_ocre_workdir(const char *working_directory) rc = create_dir_if_not_exists(images_path); if (rc) { - LOG_ERR("Failed to create OCRE images directory '%s': errno=%d", images_path, errno); + LOG_ERR("Failed to create Ocre images directory '%s': errno=%d", images_path, errno); goto finish; } @@ -190,7 +190,7 @@ struct ocre_context *ocre_create_context(const char *workdir) rc = populate_ocre_workdir(context->working_directory); if (rc) { - LOG_ERR("Failed to populate OCRE working directory: rc=%d", rc); + LOG_ERR("Failed to populate Ocre working directory: rc=%d", rc); goto error; } diff --git a/src/ocre/ocre.c b/src/ocre/ocre.c index 9c0d3fd1..a053ea4c 100644 --- a/src/ocre/ocre.c +++ b/src/ocre/ocre.c @@ -87,7 +87,7 @@ int ocre_initialize_with_runtimes(const struct ocre_runtime_vtable *const vtable int ocre_initialize(void) { - LOG_INF("Initializing OCRE %s", ocre_build_configuration.version); + LOG_INF("Initializing Ocre %s", ocre_build_configuration.version); LOG_INF("Build Commit ID: %s", ocre_build_configuration.commit_id); LOG_INF("Build Host: %s", ocre_build_configuration.build_info); diff --git a/src/runtime/wamr/wamr.c b/src/runtime/wamr/wamr.c index b4b8fbe4..bc6742e4 100644 --- a/src/runtime/wamr/wamr.c +++ b/src/runtime/wamr/wamr.c @@ -60,7 +60,7 @@ static int instance_execute(void *runtime_context) } if (context->uses_ocre_api) { - /* Cleanup module resources if using OCRE API */ + /* Cleanup module resources if using Ocre API */ LOG_INF("Cleaning up module resources"); @@ -349,12 +349,12 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s } #if CONFIG_OCRE_NETWORKING else if (!strcmp(*cap, "networking")) { - // already set up + /* already set up */ } #endif #if CONFIG_OCRE_FILESYSTEM else if (!strcmp(*cap, "filesystem")) { - // already set up + /* already set up */ } #endif else if (!strcmp(*cap, "ocre:api")) { diff --git a/src/samples/supervisor/zephyr/service.c b/src/samples/supervisor/zephyr/service.c index ebfe622e..6f4d1046 100644 --- a/src/samples/supervisor/zephyr/service.c +++ b/src/samples/supervisor/zephyr/service.c @@ -3,19 +3,20 @@ #include -// keep a reference to the single instance of the runtime +/* Keep a reference to the single instance of the runtime */ struct ocre_context *ocre_global_context = NULL; static int ocre_service_init() { - // Initialize OCRE + /* Initialize Ocre Library */ + if (ocre_initialize() != 0) { return -1; } fprintf(stderr, "Initialized Ocre\n"); - // Create a context + /* Create a context */ ocre_global_context = ocre_create_context("/lfs/ocre"); if (!ocre_global_context) { fprintf(stderr, "Failed to create Ocre context\n"); diff --git a/src/samples/supervisor/zephyr/shell.c b/src/samples/supervisor/zephyr/shell.c index 4c5ba327..7f424d68 100644 --- a/src/samples/supervisor/zephyr/shell.c +++ b/src/samples/supervisor/zephyr/shell.c @@ -13,4 +13,4 @@ static int cmd_ocre_shell(const struct shell *sh, size_t argc, char **argv) return ocre_shell(ocre_global_context, argc, argv); } -SHELL_CMD_REGISTER(ocre, NULL, "OCRE management", cmd_ocre_shell); +SHELL_CMD_REGISTER(ocre, NULL, "Ocre Runtime management", cmd_ocre_shell); diff --git a/src/shell/container/kill.c b/src/shell/container/kill.c index 6df63087..57d21438 100644 --- a/src/shell/container/kill.c +++ b/src/shell/container/kill.c @@ -8,7 +8,7 @@ static int usage(const char *argv0) { fprintf(stderr, "Usage: %s container kill CONTAINER\n", argv0); - fprintf(stderr, "\nKills a container in the OCRE context.\n"); + fprintf(stderr, "\nKills a container in the Ocre context.\n"); return -1; } diff --git a/src/shell/container/pause.c b/src/shell/container/pause.c index a14a9aa7..33ae8240 100644 --- a/src/shell/container/pause.c +++ b/src/shell/container/pause.c @@ -8,7 +8,7 @@ static int usage(const char *argv0) { fprintf(stderr, "Usage: %s container pause CONTAINER\n", argv0); - fprintf(stderr, "\nPauses a container in the OCRE context.\n"); + fprintf(stderr, "\nPauses a container in the Ocre context.\n"); return -1; } diff --git a/src/shell/container/ps.c b/src/shell/container/ps.c index e95acba1..7455e1d2 100644 --- a/src/shell/container/ps.c +++ b/src/shell/container/ps.c @@ -19,7 +19,7 @@ static const char *container_statuses[] = { static int usage(const char *argv0) { fprintf(stderr, "Usage: %s container ps [CONTAINER]\n", argv0); - fprintf(stderr, "\nList containers in OCRE context.\n"); + fprintf(stderr, "\nList containers in Ocre context.\n"); return -1; } diff --git a/src/shell/container/rm.c b/src/shell/container/rm.c index 2bcc01db..e5b9341f 100644 --- a/src/shell/container/rm.c +++ b/src/shell/container/rm.c @@ -7,7 +7,7 @@ static int usage(const char *argv0) { fprintf(stderr, "Usage: %s container rm CONTAINER\n", argv0); - fprintf(stderr, "\nRemoves a stopped container from the OCRE context.\n"); + fprintf(stderr, "\nRemoves a stopped container from the Ocre context.\n"); return -1; } diff --git a/src/shell/container/start.c b/src/shell/container/start.c index 02299b42..473c9af8 100644 --- a/src/shell/container/start.c +++ b/src/shell/container/start.c @@ -8,7 +8,7 @@ static int usage(const char *argv0) { fprintf(stderr, "Usage: %s container start CONTAINER\n", argv0); - fprintf(stderr, "\nStarts a container in the OCRE context.\n"); + fprintf(stderr, "\nStarts a container in the Ocre context.\n"); return -1; } diff --git a/src/shell/container/stop.c b/src/shell/container/stop.c index f4d5c665..1342850d 100644 --- a/src/shell/container/stop.c +++ b/src/shell/container/stop.c @@ -8,7 +8,7 @@ static int usage(const char *argv0) { fprintf(stderr, "Usage: %s container stop CONTAINER\n", argv0); - fprintf(stderr, "\nStops a container in the OCRE context.\n"); + fprintf(stderr, "\nStops a container in the Ocre context.\n"); return -1; } diff --git a/src/shell/container/unpause.c b/src/shell/container/unpause.c index 1381c07c..87a8919d 100644 --- a/src/shell/container/unpause.c +++ b/src/shell/container/unpause.c @@ -8,7 +8,7 @@ static int usage(const char *argv0) { fprintf(stderr, "Usage: %s container unpause CONTAINER\n", argv0); - fprintf(stderr, "\nUnpauses a container in the OCRE context.\n"); + fprintf(stderr, "\nUnpauses a container in the Ocre context.\n"); return -1; } diff --git a/src/shell/include/ocre/shell/shell.h b/src/shell/include/ocre/shell/shell.h index 33fb42a3..84043eeb 100644 --- a/src/shell/include/ocre/shell/shell.h +++ b/src/shell/include/ocre/shell/shell.h @@ -1,3 +1,3 @@ -#include // for context +#include int ocre_shell(struct ocre_context *ctx, int argc, char *argv[]); diff --git a/src/shell/shell.c b/src/shell/shell.c index 8283f26b..396e15e0 100644 --- a/src/shell/shell.c +++ b/src/shell/shell.c @@ -3,7 +3,7 @@ #include #include -#include // for context // maybe for api? +#include #include "command.h" #include "image.h" @@ -55,12 +55,12 @@ static int print_usage(struct ocre_context *ctx, char *argv0, int argc, char **a } static const struct ocre_command commands[] = { - // general commands + /* general commands */ {"help", print_usage}, {"version", print_version}, {"image", cmd_image}, {"container", cmd_container}, - // container shortcuts + /* container shortcuts */ {"ps", cmd_container_ps}, {"create", cmd_container_create_run}, {"run", cmd_container_create_run}, @@ -70,7 +70,7 @@ static const struct ocre_command commands[] = { // {"pause", cmd_container_pause}, // {"unpause", cmd_container_unpause}, {"rm", cmd_container_rm}, - // image shortcuts + /* image shortcuts */ {"images", cmd_image_ls}, {"pull", cmd_image_pull}, }; From 658ad6a9c493a4ff94fba0c43d2fdbcb0669c7d5 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 16 Dec 2025 23:24:54 +0100 Subject: [PATCH 130/234] ci(zephyr): add build workflow Signed-off-by: Marco Casaroli --- .github/workflows/main.yml | 9 +++++++++ .github/workflows/zephyr.yml | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 .github/workflows/zephyr.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6594d720..6b872b16 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -46,3 +46,12 @@ jobs: devcontainer-tag: ${{ needs.linux-devcontainer.outputs.devcontainer-tag }} ref: ${{ github.sha }} + zephyr: + name: Zephyr + needs: + - zephyr-devcontainer + uses: ./.github/workflows/zephyr.yml + secrets: inherit + with: + devcontainer-tag: ${{ needs.zephyr-devcontainer.outputs.devcontainer-tag }} + ref: ${{ github.sha }} diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml new file mode 100644 index 00000000..51d1f7ff --- /dev/null +++ b/.github/workflows/zephyr.yml @@ -0,0 +1,32 @@ +name: Zephyr + +on: + workflow_call: + inputs: + devcontainer-tag: + description: The container tag to be used + default: latest + required: false + type: string + ref: + type: string + required: true + +jobs: + build-zephyr: + name: Zephyr build + runs-on: ubuntu-latest + container: + image: ghcr.io/${{ github.repository }}/devcontainer-zephyr:${{ inputs.devcontainer-tag }} + options: --user 1000:127 + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: true + + - name: West init + run: . ~/.venv/bin/activate && west init -l . + + - name: West update + run: . ~/.venv/bin/activate && west update From af743b14cdb55980b7052896ce23197e30ed247e Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 00:00:58 +0100 Subject: [PATCH 131/234] ci(zephyr): remove user override We now have the proper github user in the container. Signed-off-by: Marco Casaroli --- .github/workflows/zephyr.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index 51d1f7ff..62c1d034 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -18,7 +18,6 @@ jobs: runs-on: ubuntu-latest container: image: ghcr.io/${{ github.repository }}/devcontainer-zephyr:${{ inputs.devcontainer-tag }} - options: --user 1000:127 steps: - name: Checkout uses: actions/checkout@v4 From 7721391f404bf5fae32c7423b5f72851a0bd1f4c Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 00:04:18 +0100 Subject: [PATCH 132/234] ci(zephyr): fix .venv path Signed-off-by: Marco Casaroli --- .github/workflows/zephyr.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index 62c1d034..2062b0f4 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -25,7 +25,7 @@ jobs: submodules: true - name: West init - run: . ~/.venv/bin/activate && west init -l . + run: . /home/ocre-dev/.venv/bin/activate && west init -l . - name: West update - run: . ~/.venv/bin/activate && west update + run: . /home/ocre-dev/.venv/bin/activate && west update From def42ef1874e00f01773706d5b75513ffb330a4e Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 00:19:19 +0100 Subject: [PATCH 133/234] ci(zephyr): add build matrix Signed-off-by: Marco Casaroli --- .github/workflows/zephyr.yml | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index 2062b0f4..ed784cde 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -18,6 +18,14 @@ jobs: runs-on: ubuntu-latest container: image: ghcr.io/${{ github.repository }}/devcontainer-zephyr:${{ inputs.devcontainer-tag }} + strategy: + matrix: + board: + - pico_plus2/rp2350b/m33 + app: + - src/samples/mini/zephyr + - src/samples/demo/zephyr + - src/samples/supervisor/zephyr steps: - name: Checkout uses: actions/checkout@v4 @@ -25,7 +33,16 @@ jobs: submodules: true - name: West init - run: . /home/ocre-dev/.venv/bin/activate && west init -l . + run: | + . /home/ocre-dev/.venv/bin/activate + west init -l . - name: West update - run: . /home/ocre-dev/.venv/bin/activate && west update + run: | + . /home/ocre-dev/.venv/bin/activate + west update + + - name: West build + run: | + . /home/ocre-dev/.venv/bin/activate + west build -p always -b ${{ matrix.board }} ${{ matrix.app }} From 88f1b391430e7bf7a5e561e1001cdcf1c2d49b6a Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 00:25:46 +0100 Subject: [PATCH 134/234] ci(zephyr): build zephyr samples Signed-off-by: Marco Casaroli --- .github/workflows/zephyr.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index ed784cde..f7c80570 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -32,6 +32,9 @@ jobs: with: submodules: true + - name: Configure West SDK + run: cp -r /home/ocre-dev/.cmake ~ + - name: West init run: | . /home/ocre-dev/.venv/bin/activate From f46f91cc9f6e8f6d2ad43ac4270dc42a48d79d45 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 00:36:30 +0100 Subject: [PATCH 135/234] fix(samples/demo): remove spurious include Signed-off-by: Marco Casaroli --- src/samples/demo/zephyr/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/samples/demo/zephyr/CMakeLists.txt b/src/samples/demo/zephyr/CMakeLists.txt index cacf8b37..4371bd1c 100644 --- a/src/samples/demo/zephyr/CMakeLists.txt +++ b/src/samples/demo/zephyr/CMakeLists.txt @@ -8,8 +8,6 @@ list(APPEND ZEPHYR_EXTRA_MODULES ${CMAKE_CURRENT_LIST_DIR}/../../../..) include(../demo_containers.cmake) -include(../../../../cmake/sample_containers.cmake) - find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project (ocre_sample_mini) From 1a0a6f593e47024dcd79e9f258680b8e41fa1954 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 00:38:54 +0100 Subject: [PATCH 136/234] fix(samples/zephyr): add pico_plus2 conf and overlay Signed-off-by: Marco Casaroli --- .../zephyr/boards/pico_plus2_rp2350b_m33.conf | 2 ++ .../boards/pico_plus2_rp2350b_m33.overlay | 29 +++++++++++++++++++ .../zephyr/boards/pico_plus2_rp2350b_m33.conf | 2 ++ .../boards/pico_plus2_rp2350b_m33.overlay | 29 +++++++++++++++++++ .../zephyr/boards/pico_plus2_rp2350b_m33.conf | 4 +++ .../boards/pico_plus2_rp2350b_m33.overlay | 29 +++++++++++++++++++ 6 files changed, 95 insertions(+) create mode 100644 src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33.conf create mode 100644 src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33.overlay create mode 100644 src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33.conf create mode 100644 src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33.overlay create mode 100644 src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33.conf create mode 100644 src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33.overlay diff --git a/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33.conf b/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33.conf new file mode 100644 index 00000000..fd303152 --- /dev/null +++ b/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33.conf @@ -0,0 +1,2 @@ +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_SHARED_MULTI_HEAP=y diff --git a/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33.overlay b/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33.overlay new file mode 100644 index 00000000..383637bc --- /dev/null +++ b/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33.overlay @@ -0,0 +1,29 @@ +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + storage_partition: partition@600000 { + label = "storage"; + reg = <0x410000 0x800000>; + }; + }; +}; + +/ { + fstab { + compatible = "zephyr,fstab"; + lfs1: lfs1 { + compatible = "zephyr,fstab,littlefs"; + read-size = <256>; + prog-size = <256>; + cache-size = <256>; + lookahead-size = <256>; + block-cycles = <512>; + partition = <&storage_partition>; + mount-point = "/lfs"; + automount; + }; + }; +}; diff --git a/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33.conf b/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33.conf new file mode 100644 index 00000000..fd303152 --- /dev/null +++ b/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33.conf @@ -0,0 +1,2 @@ +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_SHARED_MULTI_HEAP=y diff --git a/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33.overlay b/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33.overlay new file mode 100644 index 00000000..383637bc --- /dev/null +++ b/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33.overlay @@ -0,0 +1,29 @@ +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + storage_partition: partition@600000 { + label = "storage"; + reg = <0x410000 0x800000>; + }; + }; +}; + +/ { + fstab { + compatible = "zephyr,fstab"; + lfs1: lfs1 { + compatible = "zephyr,fstab,littlefs"; + read-size = <256>; + prog-size = <256>; + cache-size = <256>; + lookahead-size = <256>; + block-cycles = <512>; + partition = <&storage_partition>; + mount-point = "/lfs"; + automount; + }; + }; +}; diff --git a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33.conf b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33.conf new file mode 100644 index 00000000..880b21ea --- /dev/null +++ b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33.conf @@ -0,0 +1,4 @@ +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_SHARED_MULTI_HEAP=y +CONFIG_WIFI=y +CONFIG_NET_L2_WIFI_SHELL=y diff --git a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33.overlay b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33.overlay new file mode 100644 index 00000000..383637bc --- /dev/null +++ b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33.overlay @@ -0,0 +1,29 @@ +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + storage_partition: partition@600000 { + label = "storage"; + reg = <0x410000 0x800000>; + }; + }; +}; + +/ { + fstab { + compatible = "zephyr,fstab"; + lfs1: lfs1 { + compatible = "zephyr,fstab,littlefs"; + read-size = <256>; + prog-size = <256>; + cache-size = <256>; + lookahead-size = <256>; + block-cycles = <512>; + partition = <&storage_partition>; + mount-point = "/lfs"; + automount; + }; + }; +}; From 9208e29993f36fc501cc8e4963225a7ab92360dc Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 00:39:16 +0100 Subject: [PATCH 137/234] ci(linux): do not specify user It is not necessary anymore because the containers already sets it. Signed-off-by: Marco Casaroli --- .github/workflows/linux.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index c1561bb0..e00a5a37 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -18,7 +18,6 @@ jobs: runs-on: ubuntu-latest container: image: ghcr.io/${{ github.repository }}/devcontainer-linux:${{ inputs.devcontainer-tag }} - options: --user 1001:127 steps: - name: Checkout uses: actions/checkout@v4 From b64b86b943cc9f46efb3a5aa990112e76c9bce7c Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 00:48:18 +0100 Subject: [PATCH 138/234] ci(zephyr): upload build artifacts Signed-off-by: Marco Casaroli --- .github/workflows/zephyr.yml | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index f7c80570..270307a3 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -23,9 +23,9 @@ jobs: board: - pico_plus2/rp2350b/m33 app: - - src/samples/mini/zephyr - - src/samples/demo/zephyr - - src/samples/supervisor/zephyr + - mini + - demo + - supervisor steps: - name: Checkout uses: actions/checkout@v4 @@ -48,4 +48,20 @@ jobs: - name: West build run: | . /home/ocre-dev/.venv/bin/activate - west build -p always -b ${{ matrix.board }} ${{ matrix.app }} + west build -p always -b ${{ matrix.board }} src/samples/${{ matrix.app }}/zephyr + + - name: Set sane board name + run: | + BOARD=${{ matrix.board }} + echo "BOARD_NAME=$(printf "%s\n" "$BOARD" | tr / _)" >> $GITHUB_ENV + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: ocre-zephyr-${{ env.BOARD_NAME }}-${{ matrix.app }} + path: | + build/zephyr/zephyr.elf + build/zephyr/zephyr.exe + build/zephyr/zephyr.bin + build/zephyr/zephyr.dts + build/zephyr/.config From 258dca702df9296fb444f4ceac585724ac7fb85c Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 02:05:48 +0100 Subject: [PATCH 139/234] ci(zephir): add native_sim target Signed-off-by: Marco Casaroli --- .github/workflows/zephyr.yml | 2 ++ .../demo/zephyr/boards/native_sim_64.conf | 1 + .../demo/zephyr/boards/native_sim_64.overlay | 24 +++++++++++++++++++ .../mini/zephyr/boards/native_sim_64.conf | 1 + .../mini/zephyr/boards/native_sim_64.overlay | 24 +++++++++++++++++++ 5 files changed, 52 insertions(+) create mode 100644 src/samples/demo/zephyr/boards/native_sim_64.conf create mode 100644 src/samples/demo/zephyr/boards/native_sim_64.overlay create mode 100644 src/samples/mini/zephyr/boards/native_sim_64.conf create mode 100644 src/samples/mini/zephyr/boards/native_sim_64.overlay diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index 270307a3..8c24e4a8 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -22,6 +22,7 @@ jobs: matrix: board: - pico_plus2/rp2350b/m33 + - native_sim/native/64 app: - mini - demo @@ -59,6 +60,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: ocre-zephyr-${{ env.BOARD_NAME }}-${{ matrix.app }} + include-hidden-files: true path: | build/zephyr/zephyr.elf build/zephyr/zephyr.exe diff --git a/src/samples/demo/zephyr/boards/native_sim_64.conf b/src/samples/demo/zephyr/boards/native_sim_64.conf new file mode 100644 index 00000000..9d6871c3 --- /dev/null +++ b/src/samples/demo/zephyr/boards/native_sim_64.conf @@ -0,0 +1 @@ +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=10485760 diff --git a/src/samples/demo/zephyr/boards/native_sim_64.overlay b/src/samples/demo/zephyr/boards/native_sim_64.overlay new file mode 100644 index 00000000..ee78945a --- /dev/null +++ b/src/samples/demo/zephyr/boards/native_sim_64.overlay @@ -0,0 +1,24 @@ +/ { + fstab { + compatible = "zephyr,fstab"; + lfs1: lfs1 { + compatible = "zephyr,fstab,littlefs"; + read-size = <256>; + prog-size = <256>; + cache-size = <256>; + lookahead-size = <256>; + block-cycles = <512>; + partition = <&storage_partition>; + mount-point = "/lfs"; + automount; + }; + }; +}; + +&flash0 { + reg = < 0x0 DT_SIZE_M(32) >; +}; + +&storage_partition { + reg = < 0xfc000 DT_SIZE_M(16) >; +}; diff --git a/src/samples/mini/zephyr/boards/native_sim_64.conf b/src/samples/mini/zephyr/boards/native_sim_64.conf new file mode 100644 index 00000000..9d6871c3 --- /dev/null +++ b/src/samples/mini/zephyr/boards/native_sim_64.conf @@ -0,0 +1 @@ +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=10485760 diff --git a/src/samples/mini/zephyr/boards/native_sim_64.overlay b/src/samples/mini/zephyr/boards/native_sim_64.overlay new file mode 100644 index 00000000..ee78945a --- /dev/null +++ b/src/samples/mini/zephyr/boards/native_sim_64.overlay @@ -0,0 +1,24 @@ +/ { + fstab { + compatible = "zephyr,fstab"; + lfs1: lfs1 { + compatible = "zephyr,fstab,littlefs"; + read-size = <256>; + prog-size = <256>; + cache-size = <256>; + lookahead-size = <256>; + block-cycles = <512>; + partition = <&storage_partition>; + mount-point = "/lfs"; + automount; + }; + }; +}; + +&flash0 { + reg = < 0x0 DT_SIZE_M(32) >; +}; + +&storage_partition { + reg = < 0xfc000 DT_SIZE_M(16) >; +}; From 99bcf535a96bdb3e576f013139966fa852c410a1 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 02:09:35 +0100 Subject: [PATCH 140/234] ci(zephyr): test native_sim mini and demo Signed-off-by: Marco Casaroli --- .github/workflows/zephyr.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index 8c24e4a8..a8feadc7 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -67,3 +67,17 @@ jobs: build/zephyr/zephyr.bin build/zephyr/zephyr.dts build/zephyr/.config + + - name: Test native_sim mini + if: startsWith(matrix.board, 'native_sim/') && matrix.app == 'mini' + run: | + EXPECTED_LOG="powered by Ocre" + echo "Running application..." + stdbuf -oL -eL timeout 20s ./build/zephyr/zephyr.exe | tee zephyr_run.log + echo "===== Checking for expected log =====" + if grep -q "$EXPECTED_LOG" zephyr_run.log; then + echo "[OK] Found expected log: $EXPECTED_LOG" + else + echo "[ERROR] Expected log not found: $EXPECTED_LOG" + exit 1 + fi From 5b11de743e936f4974e88aa85331f198d381a723 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 02:21:12 +0100 Subject: [PATCH 141/234] fix(samples/zephyr/demo): do not build hex by default It will not work on native_sim Signed-off-by: Marco Casaroli --- src/samples/demo/zephyr/prj.conf | 1 - zephyr/wamr.cmake | 18 +++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/samples/demo/zephyr/prj.conf b/src/samples/demo/zephyr/prj.conf index 938fa212..b3c7b01b 100644 --- a/src/samples/demo/zephyr/prj.conf +++ b/src/samples/demo/zephyr/prj.conf @@ -15,7 +15,6 @@ CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=-1 CONFIG_OCRE=y CONFIG_OCRE_TIMER=y CONFIG_OCRE_CONTAINER_MESSAGING=y -CONFIG_OCRE_MERGE_HEX=y CONFIG_OCRE_WAMR_AOT=y CONFIG_OCRE_SHARED_HEAP=y #CONFIG_OCRE_GPIO=y diff --git a/zephyr/wamr.cmake b/zephyr/wamr.cmake index 0bda2b0c..701f89de 100644 --- a/zephyr/wamr.cmake +++ b/zephyr/wamr.cmake @@ -12,16 +12,20 @@ elseif (DEFINED CONFIG_XTENSA) elseif (DEFINED CONFIG_RISCV) set(TARGET_ISA RISCV32) elseif (DEFINED CONFIG_ARCH_POSIX) - if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)") + execute_process( + COMMAND uname -m + OUTPUT_VARIABLE UNAME_M + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + message(STATUS "UNAME_M: ${UNAME_M}") + if (UNAME_M MATCHES "^(arm64|aarch64)") set (TARGET_ISA "AARCH64") - elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") + elseif (UNAME_M STREQUAL "riscv64") set (TARGET_ISA "RISCV64") - elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) - # Build as X86_64 by default in 64-bit platform - set (TARGET_ISA "X86_64") - elseif (CMAKE_SIZEOF_VOID_P EQUAL 4) - # Build as X86_32 by default in 32-bit platform + elseif (UNAME_M STREQUAL "i686") set (TARGET_ISA "X86_32") + elseif (UNAME_M STREQUAL "x86_64") + set (TARGET_ISA "X86_64") else () message(SEND_ERROR "Unsupported build target platform!") endif () From db5b168854ec3906cb219cb7c54a530add27dd6e Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 02:40:57 +0100 Subject: [PATCH 142/234] fix(samples/mini/zephyr): exit simulator when native_sim We need to explicitly exit if we are running the Zephyr native_sim target. Signed-off-by: Marco Casaroli --- src/samples/mini/main.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/samples/mini/main.c b/src/samples/mini/main.c index 4991b1dc..e2ca7f0e 100644 --- a/src/samples/mini/main.c +++ b/src/samples/mini/main.c @@ -8,6 +8,10 @@ #include +#ifdef CONFIG_ARCH_POSIX +#include "nsi_main.h" +#endif + extern const unsigned char ocre_mini_sample_image[]; extern const size_t ocre_mini_sample_image_len; @@ -105,5 +109,11 @@ int main(int argc, char *argv[]) ocre_deinitialize(); +/* Exit simulator on zephyr */ + +#ifdef CONFIG_ARCH_POSIX + nsi_exit(0); +#endif + return 0; } From ee81233b4044a3d3fefa57937149682f9e895b3e Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 03:19:12 +0100 Subject: [PATCH 143/234] fix(random_id): include missing include stddef.h is required for size_t Signed-off-by: Marco Casaroli --- src/ocre/unique_random_id.c | 1 + src/ocre/unique_random_id.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/ocre/unique_random_id.c b/src/ocre/unique_random_id.c index d10e2520..1d8dc10d 100644 --- a/src/ocre/unique_random_id.c +++ b/src/ocre/unique_random_id.c @@ -1,3 +1,4 @@ +#include #include #include diff --git a/src/ocre/unique_random_id.h b/src/ocre/unique_random_id.h index b6b389d5..ad771374 100644 --- a/src/ocre/unique_random_id.h +++ b/src/ocre/unique_random_id.h @@ -1,3 +1,5 @@ +#include + #include int make_unique_random_container_id(const struct ocre_context *context, char *container_id, size_t len); From 28640993558ee69a85cb0bb39b6e7760928f4a9a Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 03:20:42 +0100 Subject: [PATCH 144/234] chore: cleanup and formatting Remove spurious comments and minor fixes to formatting. Signed-off-by: Marco Casaroli --- src/runtime/wamr/ocre_api/CMakeLists.txt | 6 ------ src/samples/demo/zephyr/boards/native_sim_64.overlay | 2 +- src/samples/mini/zephyr/boards/native_sim_64.overlay | 2 +- src/samples/supervisor/zephyr/boards/native_sim_64.overlay | 2 +- src/samples/supervisor/zephyr/service.c | 2 ++ zephyr/CMakeLists.txt | 1 - 6 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/runtime/wamr/ocre_api/CMakeLists.txt b/src/runtime/wamr/ocre_api/CMakeLists.txt index d3b00299..156199e8 100644 --- a/src/runtime/wamr/ocre_api/CMakeLists.txt +++ b/src/runtime/wamr/ocre_api/CMakeLists.txt @@ -16,14 +16,8 @@ target_sources(OcreRuntimeAPI ) -# target_include_directories(OcreRuntimeAPI -# PUBLIC -# include -# ) - target_link_libraries(OcreRuntimeAPI PUBLIC - # OcreRuntime OcrePlatform vmlib ) diff --git a/src/samples/demo/zephyr/boards/native_sim_64.overlay b/src/samples/demo/zephyr/boards/native_sim_64.overlay index ee78945a..e4e1c86c 100644 --- a/src/samples/demo/zephyr/boards/native_sim_64.overlay +++ b/src/samples/demo/zephyr/boards/native_sim_64.overlay @@ -16,7 +16,7 @@ }; &flash0 { - reg = < 0x0 DT_SIZE_M(32) >; + reg = < 0x0 DT_SIZE_M(32) >; }; &storage_partition { diff --git a/src/samples/mini/zephyr/boards/native_sim_64.overlay b/src/samples/mini/zephyr/boards/native_sim_64.overlay index ee78945a..e4e1c86c 100644 --- a/src/samples/mini/zephyr/boards/native_sim_64.overlay +++ b/src/samples/mini/zephyr/boards/native_sim_64.overlay @@ -16,7 +16,7 @@ }; &flash0 { - reg = < 0x0 DT_SIZE_M(32) >; + reg = < 0x0 DT_SIZE_M(32) >; }; &storage_partition { diff --git a/src/samples/supervisor/zephyr/boards/native_sim_64.overlay b/src/samples/supervisor/zephyr/boards/native_sim_64.overlay index ee78945a..e4e1c86c 100644 --- a/src/samples/supervisor/zephyr/boards/native_sim_64.overlay +++ b/src/samples/supervisor/zephyr/boards/native_sim_64.overlay @@ -16,7 +16,7 @@ }; &flash0 { - reg = < 0x0 DT_SIZE_M(32) >; + reg = < 0x0 DT_SIZE_M(32) >; }; &storage_partition { diff --git a/src/samples/supervisor/zephyr/service.c b/src/samples/supervisor/zephyr/service.c index 6f4d1046..b00a5752 100644 --- a/src/samples/supervisor/zephyr/service.c +++ b/src/samples/supervisor/zephyr/service.c @@ -4,6 +4,7 @@ #include /* Keep a reference to the single instance of the runtime */ + struct ocre_context *ocre_global_context = NULL; static int ocre_service_init() @@ -17,6 +18,7 @@ static int ocre_service_init() fprintf(stderr, "Initialized Ocre\n"); /* Create a context */ + ocre_global_context = ocre_create_context("/lfs/ocre"); if (!ocre_global_context) { fprintf(stderr, "Failed to create Ocre context\n"); diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index dc626e13..7b61aa57 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -10,7 +10,6 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_C_STANDARD 99) set(CMAKE_CXX_STANDARD 17) -# include (../cmake/build_information.cmake) include (wamr.cmake) add_subdirectory(../src/ocre "ocre-core") From 9c1331d068d60ec8485000eaf2e1c5c119967a99 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 03:21:13 +0100 Subject: [PATCH 145/234] fix(pico_plus2): do not enable wifi These boards do not come with Wifi. Signed-off-by: Marco Casaroli --- .../supervisor/zephyr/boards/pico_plus2_rp2350b_m33.conf | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33.conf b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33.conf index 880b21ea..fd303152 100644 --- a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33.conf +++ b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33.conf @@ -1,4 +1,2 @@ CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_SHARED_MULTI_HEAP=y -CONFIG_WIFI=y -CONFIG_NET_L2_WIFI_SHELL=y From 3e1a97650a71bc1a852538ba8dd1f577db32961c Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 03:41:42 +0100 Subject: [PATCH 146/234] fix(zephyr/wamr): handle AOT configuration Signed-off-by: Marco Casaroli --- zephyr/wamr.cmake | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/zephyr/wamr.cmake b/zephyr/wamr.cmake index 701f89de..fa204c93 100644 --- a/zephyr/wamr.cmake +++ b/zephyr/wamr.cmake @@ -17,7 +17,6 @@ elseif (DEFINED CONFIG_ARCH_POSIX) OUTPUT_VARIABLE UNAME_M OUTPUT_STRIP_TRAILING_WHITESPACE ) - message(STATUS "UNAME_M: ${UNAME_M}") if (UNAME_M MATCHES "^(arm64|aarch64)") set (TARGET_ISA "AARCH64") elseif (UNAME_M STREQUAL "riscv64") @@ -39,7 +38,11 @@ set(WAMR_BUILD_PLATFORM "zephyr") set(WAMR_BUILD_TARGET ${TARGET_ISA}) set(WAMR_BUILD_INTERP 1) set(WAMR_BUILD_FAST_INTERP 0) -set(WAMR_BUILD_AOT 1) +if (CONFIG_OCRE_WAMR_AOT) + set(WAMR_BUILD_AOT 1) +else() + set(WAMR_BUILD_AOT 0) +endif() set(WAMR_BUILD_JIT 0) set(WAMR_BUILD_LIBC_BUILTIN 0) set(WAMR_BUILD_LIBC_WASI 1) From a79a53d568c7467efc48d1c76aef9f24a28d5eb4 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 03:50:05 +0100 Subject: [PATCH 147/234] build: honor WAMR log level configuration On Zephyr, this is defined by Kconfig. On linux by config.h. Signed-off-by: Marco Casaroli --- .../posix/include/ocre/platform/config.h | 32 +++++++++---------- src/runtime/wamr/wamr.c | 2 +- zephyr/Kconfig | 2 +- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/platform/posix/include/ocre/platform/config.h b/src/platform/posix/include/ocre/platform/config.h index 481a4b78..4035179f 100644 --- a/src/platform/posix/include/ocre/platform/config.h +++ b/src/platform/posix/include/ocre/platform/config.h @@ -1,23 +1,21 @@ #ifndef OCRE_PLATFORM_POSIX_H #define OCRE_PLATFORM_POSIX_H -#define CONFIG_OCRE_DEFAULT_WORKING_DIRECTORY "src/ocre/var/lib/ocre" +#define CONFIG_OCRE_DEFAULT_WORKING_DIRECTORY "src/ocre/var/lib/ocre" -#define CONFIG_OCRE_WAMR_INTERPRETER 1 -#define CONFIG_OCRE_WAMR_AOT 1 -#define CONFIG_OCRE_WAMR_HEAP_BUFFER_SIZE 32768 -#define CONFIG_OCRE_CONTAINER_DEFAULT_HEAP_SIZE 4096 -#define CONFIG_OCRE_CONTAINER_DEFAULT_STACK_SIZE 2048 -#define CONFIG_OCRE_TIMER 1 -#define CONFIG_OCRE_MAX_TIMERS 5 -#define CONFIG_OCRE_LOG_LEVEL_DEFAULT 3 -#define CONFIG_OCRE_LOG_LEVEL 4 -#define CONFIG_OCRE_NETWORKING 1 -#define CONFIG_OCRE_FILESYSTEM 1 -#define CONFIG_OCRE_CONTAINER_MESSAGING 1 -#define CONFIG_OCRE_MESSAGING_MAX_SUBSCRIPTIONS 32 -#define CONFIG_OCRE_SHARED_HEAP 1 -#define CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL 1 -#define CONFIG_OCRE_SHARED_HEAP_BUF_SIZE 131072 +#define CONFIG_OCRE_WAMR_INTERPRETER 1 +#define CONFIG_OCRE_WAMR_AOT 1 +#define CONFIG_OCRE_TIMER 1 +#define CONFIG_OCRE_MAX_TIMERS 5 +#define CONFIG_OCRE_LOG_LEVEL_DEFAULT 3 +#define CONFIG_OCRE_LOG_LEVEL 4 +#define CONFIG_OCRE_NETWORKING 1 +#define CONFIG_OCRE_FILESYSTEM 1 +#define CONFIG_OCRE_CONTAINER_MESSAGING 1 +#define CONFIG_OCRE_MESSAGING_MAX_SUBSCRIPTIONS 32 +#define CONFIG_OCRE_SHARED_HEAP 1 +#define CONFIG_OCRE_SHARED_HEAP_BUF_VIRTUAL 1 +#define CONFIG_OCRE_SHARED_HEAP_BUF_SIZE 131072 +#define CONFIG_OCRE_WAMR_LOG_LEVEL 2 #endif /* OCRE_PLATFORM_POSIX_H */ diff --git a/src/runtime/wamr/wamr.c b/src/runtime/wamr/wamr.c index bc6742e4..26eebb18 100644 --- a/src/runtime/wamr/wamr.c +++ b/src/runtime/wamr/wamr.c @@ -115,7 +115,7 @@ static int runtime_init(void) goto error_sh_heap_buf; } - wasm_runtime_set_log_level(WASM_LOG_LEVEL_VERBOSE); + wasm_runtime_set_log_level(CONFIG_OCRE_WAMR_LOG_LEVEL); #ifdef CONFIG_OCRE_SHARED_HEAP SharedHeapInitArgs heap_init_args; diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 113e3b70..2980e686 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -209,7 +209,7 @@ source "subsys/logging/Kconfig.template.log_config" config OCRE_WAMR_LOG_LEVEL int "Log level for WAMR" - default 0 + default 2 range 0 4 help Set the log level for the WAMR runtime: From 0ed2f96649ec69519274d9def626879ced4560b1 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 03:51:45 +0100 Subject: [PATCH 148/234] fix(kconfig): fix filesystem configuration The correct name is just OCRE_FILESYSTEM. Signed-off-by: Marco Casaroli --- zephyr/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 2980e686..f67111c5 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -100,7 +100,7 @@ config OCRE_NETWORKING help Enable networking support for containers. -config OCRE_CONTAINER_FILESYSTEM +config OCRE_FILESYSTEM bool "Enable Container file system support" default n help From f59131b86b14f24699146d2064076fdd15eafc24 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 03:52:19 +0100 Subject: [PATCH 149/234] chore(kconfig): removed unused configuration Signed-off-by: Marco Casaroli --- zephyr/Kconfig | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index f67111c5..e07e78af 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -75,18 +75,6 @@ config OCRE_WAMR_AOT help Enable execution of ahead of time compiled code. -config OCRE_CONTAINER_DEFAULT_HEAP_SIZE - int "Default value for the container heap size" - default 4096 - help - The default value used for a container's heap size. - -config OCRE_CONTAINER_DEFAULT_STACK_SIZE - int "Default value for the container stack size" - default 2048 - help - The default value used for a container's stack size. - comment "Container features" config OCRE_NETWORKING From d6c9423a97bc177fc3d1f4b57670b03af7d8ada6 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 04:35:32 +0100 Subject: [PATCH 150/234] build(samples/posix): handle pthread properly Using CMake to figure out how to deal with threads is the preferrable way of managing the link options for it. Signed-off-by: Marco Casaroli --- src/samples/bash_runtime/posix/CMakeLists.txt | 7 +++---- src/samples/demo/posix/CMakeLists.txt | 7 +++---- src/samples/mini/posix/CMakeLists.txt | 7 +++---- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/samples/bash_runtime/posix/CMakeLists.txt b/src/samples/bash_runtime/posix/CMakeLists.txt index 7b014703..e97e7b45 100644 --- a/src/samples/bash_runtime/posix/CMakeLists.txt +++ b/src/samples/bash_runtime/posix/CMakeLists.txt @@ -15,7 +15,6 @@ target_link_libraries(ocre_bash OcreRuntimeBash ) -target_link_libraries(ocre_bash - PRIVATE - -lpthread -) +set(THREADS_PREFER_PTHREAD_FLAG TRUE) +find_package(Threads) +target_link_libraries(ocre_bash PRIVATE Threads::Threads) diff --git a/src/samples/demo/posix/CMakeLists.txt b/src/samples/demo/posix/CMakeLists.txt index ec37f85f..3129b750 100644 --- a/src/samples/demo/posix/CMakeLists.txt +++ b/src/samples/demo/posix/CMakeLists.txt @@ -11,7 +11,6 @@ target_link_libraries(ocre_demo OcreCore ) -target_link_libraries(ocre_demo - PRIVATE - -lpthread -) +set(THREADS_PREFER_PTHREAD_FLAG TRUE) +find_package(Threads) +target_link_libraries(ocre_demo PRIVATE Threads::Threads) diff --git a/src/samples/mini/posix/CMakeLists.txt b/src/samples/mini/posix/CMakeLists.txt index a9934829..597131d5 100644 --- a/src/samples/mini/posix/CMakeLists.txt +++ b/src/samples/mini/posix/CMakeLists.txt @@ -14,7 +14,6 @@ target_link_libraries(ocre_mini OcreCore ) -target_link_libraries(ocre_mini - PRIVATE - -lpthread -) +set(THREADS_PREFER_PTHREAD_FLAG TRUE) +find_package(Threads) +target_link_libraries(ocre_mini PRIVATE Threads::Threads) From 103e7fd2382a86cc1a89048d6b63542e45152469 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 04:49:54 +0100 Subject: [PATCH 151/234] fix(container): remove ocre_container_id_compare This function is not necessary anymore as we can just get the id from the container and strcmp ourselves. Signed-off-by: Marco Casaroli --- src/ocre/container.c | 10 ---------- src/ocre/container.h | 1 - src/ocre/context.c | 8 +++++++- src/shell/image/pull.c | 2 +- 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/ocre/container.c b/src/ocre/container.c index 7983389a..187ad476 100644 --- a/src/ocre/container.c +++ b/src/ocre/container.c @@ -658,13 +658,3 @@ const char *ocre_container_get_image(const struct ocre_container *container) return container->image; } - -int ocre_container_id_compare(const struct ocre_container *container, const char *id) -{ - if (!container || !id) { - LOG_ERR("Invalid container or id"); - return -1; - } - - return strcmp(container->id, id); -} diff --git a/src/ocre/container.h b/src/ocre/container.h index 79c10437..4c688b08 100644 --- a/src/ocre/container.h +++ b/src/ocre/container.h @@ -6,4 +6,3 @@ struct ocre_container *ocre_container_create(const char *img_path, const char *w const char *container_id, bool detached, const struct ocre_container_args *arguments); int ocre_container_destroy(struct ocre_container *container); -int ocre_container_id_compare(const struct ocre_container *container, const char *id); diff --git a/src/ocre/context.c b/src/ocre/context.c index 4e0acc27..52dfd570 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -224,7 +224,13 @@ struct ocre_container *ocre_context_get_container_by_id_locked(const struct ocre LL_FOREACH(context->containers, node) { - if (!ocre_container_id_compare(node->container, id)) { + const char *container_id = ocre_container_get_id(node->container); + if (!container_id) { + LOG_ERR("Failed to get container ID"); + return NULL; + } + + if (!strcmp(container_id, id)) { return node->container; } } diff --git a/src/shell/image/pull.c b/src/shell/image/pull.c index 705b5a20..b68bee7b 100644 --- a/src/shell/image/pull.c +++ b/src/shell/image/pull.c @@ -49,7 +49,7 @@ int cmd_image_pull(struct ocre_context *ctx, char *argv0, int argc, char **argv) } } - char *working_directory = ocre_context_get_working_directory(ctx); + const char *working_directory = ocre_context_get_working_directory(ctx); char *image_path = malloc(strlen(working_directory) + strlen("/images/") + strlen(local_name) + 1); if (!image_path) { From 2d34d85eff270588a555fbac91ded51313b7443c Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 04:56:44 +0100 Subject: [PATCH 152/234] doc(context): returns number of written containers Update the documentation to match the code. Signed-off-by: Marco Casaroli --- src/ocre/include/ocre/ocre.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ocre/include/ocre/ocre.h b/src/ocre/include/ocre/ocre.h index 3ac95829..cc0c6b92 100644 --- a/src/ocre/include/ocre/ocre.h +++ b/src/ocre/include/ocre/ocre.h @@ -329,7 +329,7 @@ int ocre_context_get_num_containers(struct ocre_context *context); * @param[out] containers A pointer to an array of pointers to containers * @param[in] max_size The maximum size of the array * - * @return Zero on success, non-zero on failure + * @return The number of containers listed, negative on failure */ int ocre_context_list_containers(struct ocre_context *context, struct ocre_container **containers, int max_size); From 09b1c6962d159d828531c1d5c72953826432ec83 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 05:02:45 +0100 Subject: [PATCH 153/234] feat(ocre): remove ocre_initialize() function We also rename ocre_initialize_with_runtimes() to ocre_initialize() and clarify the documentation. This is to avoid confusion of having more than one function for initalization. Signed-off-by: Marco Casaroli --- src/ocre/include/ocre/ocre.h | 23 +++-------------------- src/ocre/ocre.c | 15 +++++---------- src/samples/demo/main.c | 2 +- src/samples/mini/main.c | 2 +- src/samples/supervisor/zephyr/service.c | 2 +- 5 files changed, 11 insertions(+), 33 deletions(-) diff --git a/src/ocre/include/ocre/ocre.h b/src/ocre/include/ocre/ocre.h index cc0c6b92..68fc9ae0 100644 --- a/src/ocre/include/ocre/ocre.h +++ b/src/ocre/include/ocre/ocre.h @@ -202,34 +202,17 @@ struct ocre_container_args { */ struct ocre_container; -/** - * @public - * @brief Initialize the Ocre Library - * - * This function initializes the Ocre Library. It must be called exactly once before any other Ocre Library functions - * are used. As an alternative, Ocre can be initialized with custom runtime engines using - * ocre_initialize_with_runtimes() instead. - * - * Do not call this function if you have already called ocre_initialize_with_runtimes(). - * - * @return 0 on success, non-zero on failure - */ -int ocre_initialize(void); - /** * @brief Initialize the Ocre Library and register runtime engines * - * This function initializes the Ocre Library and register additional runtime engines. It must be called exactly once - * before any other Ocre Library functions are used. As an alternative, Ocre can be initialized without custom runtime - * engines using ocre_initialize() instead. - * - * Do not call this function if you have already called ocre_initialize(). + * This function initializes the Ocre Library and register optional additional runtime engines. It must be called + * exactly once before any other Ocre Library functions are used. * * @param vtable A pointer to a NULL-terminated Array of runtime engine vtables to register. Can be NULL. * * @return 0 on success, non-zero on failure */ -int ocre_initialize_with_runtimes(const struct ocre_runtime_vtable *const vtable[]); +int ocre_initialize(const struct ocre_runtime_vtable *const vtable[]); /** * @brief Creates a new Ocre Context diff --git a/src/ocre/ocre.c b/src/ocre/ocre.c index a053ea4c..b58904ad 100644 --- a/src/ocre/ocre.c +++ b/src/ocre/ocre.c @@ -34,8 +34,12 @@ struct runtime_node { static struct runtime_node *runtimes = NULL; -int ocre_initialize_with_runtimes(const struct ocre_runtime_vtable *const vtable[]) +int ocre_initialize(const struct ocre_runtime_vtable *const vtable[]) { + LOG_INF("Initializing Ocre %s", ocre_build_configuration.version); + LOG_INF("Build Commit ID: %s", ocre_build_configuration.commit_id); + LOG_INF("Build Host: %s", ocre_build_configuration.build_info); + /* Add WAMR runtime to the list */ struct runtime_node *wamr = malloc(sizeof(struct runtime_node)); @@ -85,15 +89,6 @@ int ocre_initialize_with_runtimes(const struct ocre_runtime_vtable *const vtable return 0; } -int ocre_initialize(void) -{ - LOG_INF("Initializing Ocre %s", ocre_build_configuration.version); - LOG_INF("Build Commit ID: %s", ocre_build_configuration.commit_id); - LOG_INF("Build Host: %s", ocre_build_configuration.build_info); - - return ocre_initialize_with_runtimes((const struct ocre_runtime_vtable *const[]){NULL}); -} - const struct ocre_runtime_vtable *ocre_get_runtime(const char *name) { if (!name) { diff --git a/src/samples/demo/main.c b/src/samples/demo/main.c index 83bf0417..a90689ab 100644 --- a/src/samples/demo/main.c +++ b/src/samples/demo/main.c @@ -12,7 +12,7 @@ int main(int argc, char *argv[]) int rc; int status; - rc = ocre_initialize(); + rc = ocre_initialize(NULL); if (rc) { fprintf(stderr, "Failed to initialize runtimes\n"); return 1; diff --git a/src/samples/mini/main.c b/src/samples/mini/main.c index e2ca7f0e..916f4944 100644 --- a/src/samples/mini/main.c +++ b/src/samples/mini/main.c @@ -38,7 +38,7 @@ int main(int argc, char *argv[]) { int rc; - rc = ocre_initialize(); + rc = ocre_initialize(NULL); if (rc) { fprintf(stderr, "Failed to initialize runtimes\n"); return 1; diff --git a/src/samples/supervisor/zephyr/service.c b/src/samples/supervisor/zephyr/service.c index b00a5752..5af138aa 100644 --- a/src/samples/supervisor/zephyr/service.c +++ b/src/samples/supervisor/zephyr/service.c @@ -11,7 +11,7 @@ static int ocre_service_init() { /* Initialize Ocre Library */ - if (ocre_initialize() != 0) { + if (ocre_initialize(NULL)) { return -1; } From bf4f8e46c8ef5b8250e58a873a8ad81f1318350c Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 05:11:24 +0100 Subject: [PATCH 154/234] build: handle build date separately The build_info string was gettings too long and confusing, since it often already has some date. We move the build date to its own variable, to make it more clear. Signed-off-by: Marco Casaroli --- src/ocre/CMakeLists.txt | 3 ++- src/ocre/include/ocre/ocre.h | 1 + src/ocre/ocre.c | 4 +++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/ocre/CMakeLists.txt b/src/ocre/CMakeLists.txt index d043c54f..dddbdd89 100644 --- a/src/ocre/CMakeLists.txt +++ b/src/ocre/CMakeLists.txt @@ -26,7 +26,8 @@ file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/ocre) # Generate build info header file in binary dir for every build add_custom_command( OUTPUT include/ocre/build_info.h - COMMAND sh -c "echo \"#define OCRE_BUILD_HOST_INFO \\\"$ENV{USER} @ $(uname -a) - $(date +'%Y-%m-%d %H:%M:%S %Z')\\\"\"" > include/ocre/build_info.h + COMMAND sh -c "echo \"#define OCRE_BUILD_HOST_INFO \\\"$ENV{USER} @ $(uname -a)\\\"\"" > include/ocre/build_info.h + COMMAND sh -c "echo \"#define OCRE_BUILD_DATE \\\"$(date +'%Y-%m-%d %H:%M:%S %Z')\\\"\"" >> include/ocre/build_info.h VERBATIM DEPENDS always_rebuild ) diff --git a/src/ocre/include/ocre/ocre.h b/src/ocre/include/ocre/ocre.h index 68fc9ae0..0115d250 100644 --- a/src/ocre/include/ocre/ocre.h +++ b/src/ocre/include/ocre/ocre.h @@ -80,6 +80,7 @@ struct ocre_config { const char *version; /**< Version of the Ocre Library */ const char *commit_id; /**< Commit ID of the build tree */ const char *build_info; /**< Host build information */ + const char *build_date; /**< Build date */ }; /** diff --git a/src/ocre/ocre.c b/src/ocre/ocre.c index b58904ad..a5d654de 100644 --- a/src/ocre/ocre.c +++ b/src/ocre/ocre.c @@ -23,6 +23,7 @@ const struct ocre_config ocre_build_configuration = { .build_info = OCRE_BUILD_HOST_INFO, .version = OCRE_VERSION_STRING, .commit_id = GIT_COMMIT_ID, + .build_date = OCRE_BUILD_DATE, }; /* List of runtimes */ @@ -38,7 +39,8 @@ int ocre_initialize(const struct ocre_runtime_vtable *const vtable[]) { LOG_INF("Initializing Ocre %s", ocre_build_configuration.version); LOG_INF("Build Commit ID: %s", ocre_build_configuration.commit_id); - LOG_INF("Build Host: %s", ocre_build_configuration.build_info); + LOG_INF("Build Info: %s", ocre_build_configuration.build_info); + LOG_INF("Build Date: %s", ocre_build_configuration.build_date); /* Add WAMR runtime to the list */ From b8ee6704814eefc147620985828748dfe37e6e1c Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 05:21:57 +0100 Subject: [PATCH 155/234] chore(devcontainer): formatting Signed-off-by: Marco Casaroli --- .devcontainer/linux/devcontainer.json | 10 +++++----- .devcontainer/zephyr/devcontainer.json | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.devcontainer/linux/devcontainer.json b/.devcontainer/linux/devcontainer.json index 0ce49fe7..81a64255 100644 --- a/.devcontainer/linux/devcontainer.json +++ b/.devcontainer/linux/devcontainer.json @@ -1,6 +1,6 @@ { - "build": { - "dockerfile": "Dockerfile" - }, - "remoteUser": "ocre-dev" -} \ No newline at end of file + "build": { + "dockerfile": "Dockerfile" + }, + "remoteUser": "ocre-dev" +} diff --git a/.devcontainer/zephyr/devcontainer.json b/.devcontainer/zephyr/devcontainer.json index 2ca94ddb..791f9ec2 100644 --- a/.devcontainer/zephyr/devcontainer.json +++ b/.devcontainer/zephyr/devcontainer.json @@ -1,8 +1,8 @@ { - "build": { - "dockerfile": "Dockerfile", - "context": "../.." - }, - "remoteUser": "ocre-dev", - "postCreateCommand": "sudo chown ocre-dev /workspaces" + "build": { + "dockerfile": "Dockerfile", + "context": "../.." + }, + "remoteUser": "ocre-dev", + "postCreateCommand": "sudo chown ocre-dev /workspaces" } From 643ed610d2eb58f0a5eda7d33e5324258e282b5c Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 10:59:56 +0100 Subject: [PATCH 156/234] feat(ocre): enforce lowercase alphanumeric IDs We want to make sure the container or image id do not start with . and also only contain a-z, 0-9, ., - and _. These are converted to paths and allowing special characters would allow the user to tweak files outside of ocre workdir. Signed-off-by: Marco Casaroli --- src/ocre/context.c | 20 +++++++++++++++++++- src/ocre/include/ocre/ocre.h | 13 +++++++++++++ src/ocre/ocre.c | 28 ++++++++++++++++++++++++++++ src/shell/container/create.c | 20 ++++++++++++++++++++ src/shell/image/ls.c | 10 ++++++++++ src/shell/image/pull.c | 10 ++++++++++ src/shell/image/rm.c | 10 ++++++++++ 7 files changed, 110 insertions(+), 1 deletion(-) diff --git a/src/ocre/context.c b/src/ocre/context.c index 52dfd570..e9d14640 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -291,6 +291,24 @@ struct ocre_container *ocre_context_create_container(struct ocre_context *contex char random_id[RANDOM_ID_LEN]; int rc; + /* Check if the provided container ID is valid */ + + if (container_id && !ocre_is_valid_id(container_id)) { + LOG_ERR("Invalid characters in container ID '%s'. Valid are [a-z0-9_-.] (lowercase alphanumeric) and " + "cannot start with '.'", + container_id); + goto error; + } + + /* Check if the provided image ID is valid */ + + if (image && !ocre_is_valid_id(image)) { + LOG_ERR("Invalid characters in image ID '%s'. Valid are [a-z0-9_-.] (lowercase alphanumeric) and " + "cannot start with '.'", + image); + goto error; + } + rc = pthread_mutex_lock(&context->mutex); if (rc) { LOG_ERR("Failed to lock context mutex: rc=%d", rc); @@ -409,7 +427,7 @@ struct ocre_container *ocre_context_create_container(struct ocre_context *contex int ocre_context_remove_container(struct ocre_context *context, struct ocre_container *container) { - int rc = -1; + int rc = -1; struct container_node *node = NULL; if (!context || !container) { diff --git a/src/ocre/include/ocre/ocre.h b/src/ocre/include/ocre/ocre.h index 0115d250..6081c654 100644 --- a/src/ocre/include/ocre/ocre.h +++ b/src/ocre/include/ocre/ocre.h @@ -330,6 +330,19 @@ int ocre_context_list_containers(struct ocre_context *context, struct ocre_conta */ const char *ocre_context_get_working_directory(struct ocre_context *context); +/** + * @brief Check if a container or image ID is valid + * @memberof ocre_context + * + * Checks if a container or image ID is valid. A valid container or image ID must not be NULL, empty, or start with a + * dot '.'. It can only contain alphanumeric characters, dots, underscores, and hyphens. + * + * @param id A pointer to the container or image ID to check + * + * @return Zero if invalid, 1 if valid + */ +int ocre_is_valid_id(const char *id); + /** * @brief Start a container * @memberof ocre_container diff --git a/src/ocre/ocre.c b/src/ocre/ocre.c index a5d654de..9650efe2 100644 --- a/src/ocre/ocre.c +++ b/src/ocre/ocre.c @@ -1,6 +1,7 @@ #include #include #include +#include #include @@ -124,3 +125,30 @@ void ocre_deinitialize(void) free(elt); } } + +int ocre_is_valid_id(const char *id) +{ + /* Cannot be NULL */ + + if (!id) { + return 0; + } + + /* Cannot be empty or start with a dot '.' */ + + if (id[0] == '\0' || id[0] == '.') { + return 0; + } + + /* Can only contain alphanumeric characters, dots, underscores, and hyphens */ + + for (size_t i = 0; i < strlen(id); i++) { + if ((isalnum(id[i]) && islower(id[i])) || id[i] == '.' || id[i] == '_' || id[i] == '-') { + continue; + } + + return 0; + } + + return 1; +} diff --git a/src/shell/container/create.c b/src/shell/container/create.c index 0fc0744e..18bcd27a 100644 --- a/src/shell/container/create.c +++ b/src/shell/container/create.c @@ -69,6 +69,16 @@ int cmd_container_create_run(struct ocre_context *ctx, char *argv0, int argc, ch goto cleanup; } + /* Check if the provided container ID is valid */ + + if (optarg && !ocre_is_valid_id(optarg)) { + fprintf(stderr, + "Invalid characters in container ID '%s'. Valid are [a-z0-9_-.] " + "(lowercase alphanumeric) and cannot start with '.'\n", + optarg); + goto cleanup; + } + container_id = optarg; continue; } @@ -154,6 +164,16 @@ int cmd_container_create_run(struct ocre_context *ctx, char *argv0, int argc, ch goto cleanup; } + /* Check if the provided image ID is valid */ + + if (argv[optind] && !ocre_is_valid_id(argv[optind])) { + fprintf(stderr, + "Invalid characters in image ID '%s'. Valid are [a-z0-9_-.] (lowercase alphanumeric) and " + "cannot start with '.'", + argv[optind]); + goto cleanup; + } + const struct ocre_container_args arguments = { .argv = (const char **)&argv[optind + 1], .capabilities = capabilities, diff --git a/src/shell/image/ls.c b/src/shell/image/ls.c index 3f318a55..6c4d662e 100644 --- a/src/shell/image/ls.c +++ b/src/shell/image/ls.c @@ -114,6 +114,16 @@ int cmd_image_ls(struct ocre_context *ctx, char *argv0, int argc, char **argv) case 2: { const char *working_directory = ocre_context_get_working_directory(ctx); + /* Check if the provided image ID is valid */ + + if (argv[1] && !ocre_is_valid_id(argv[1])) { + fprintf(stderr, + "Invalid characters in image ID '%s'. Valid are [a-z0-9_-.] (lowercase " + "alphanumeric) and cannot start with '.'\n", + argv[1]); + return -1; + } + char *image_path = malloc(strlen(working_directory) + strlen("/images") + strlen(argv[1]) + 2); if (!image_path) { fprintf(stderr, "Failed to allocate memory for image path\n"); diff --git a/src/shell/image/pull.c b/src/shell/image/pull.c index b68bee7b..ce48d6ed 100644 --- a/src/shell/image/pull.c +++ b/src/shell/image/pull.c @@ -49,6 +49,16 @@ int cmd_image_pull(struct ocre_context *ctx, char *argv0, int argc, char **argv) } } + /* Check if the provided image ID is valid */ + + if (local_name && !ocre_is_valid_id(local_name)) { + fprintf(stderr, + "Invalid characters in image ID '%s'. Valid are [a-z0-9_-.] (lowercase " + "alphanumeric) and cannot start with '.'\n", + local_name); + return -1; + } + const char *working_directory = ocre_context_get_working_directory(ctx); char *image_path = malloc(strlen(working_directory) + strlen("/images/") + strlen(local_name) + 1); diff --git a/src/shell/image/rm.c b/src/shell/image/rm.c index 56b86eb4..66e8a83d 100644 --- a/src/shell/image/rm.c +++ b/src/shell/image/rm.c @@ -16,6 +16,16 @@ static int usage(const char *argv0) int cmd_image_rm(struct ocre_context *ctx, char *argv0, int argc, char **argv) { if (argc == 2) { + /* Check if the provided image ID is valid */ + + if (argv[1] && !ocre_is_valid_id(argv[1])) { + fprintf(stderr, + "Invalid characters in image ID '%s'. Valid are [a-z0-9_-.] (lowercase " + "alphanumeric) and cannot start with '.'\n", + argv[1]); + return -1; + } + const char *working_directory = ocre_context_get_working_directory(ctx); char *image_path = malloc(strlen(working_directory) + strlen("/images") + strlen(argv[1]) + 2); From 4b48aa55c032e2a9d26987faf0ecf4c927227bf8 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 11:02:22 +0100 Subject: [PATCH 157/234] chore: remove spurious sample It was just a proof of concept. This will be added back properly later. Signed-off-by: Marco Casaroli --- src/samples/bash_runtime/posix/CMakeLists.txt | 20 -- .../bash_runtime/posix/bash/CMakeLists.txt | 18 -- src/samples/bash_runtime/posix/bash/bash.c | 182 ------------------ .../bash/include/ocre/runtime/bash/bash.h | 8 - src/samples/bash_runtime/posix/main.c | 87 --------- 5 files changed, 315 deletions(-) delete mode 100644 src/samples/bash_runtime/posix/CMakeLists.txt delete mode 100644 src/samples/bash_runtime/posix/bash/CMakeLists.txt delete mode 100644 src/samples/bash_runtime/posix/bash/bash.c delete mode 100644 src/samples/bash_runtime/posix/bash/include/ocre/runtime/bash/bash.h delete mode 100644 src/samples/bash_runtime/posix/main.c diff --git a/src/samples/bash_runtime/posix/CMakeLists.txt b/src/samples/bash_runtime/posix/CMakeLists.txt deleted file mode 100644 index e97e7b45..00000000 --- a/src/samples/bash_runtime/posix/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -cmake_minimum_required(VERSION 3.20.0) - -project (ocre_sample_bash_runtime) - -add_subdirectory(bash) - -add_executable(ocre_bash - main.c -) - -target_link_libraries(ocre_bash - PUBLIC - OcreCore - OcreRuntime - OcreRuntimeBash -) - -set(THREADS_PREFER_PTHREAD_FLAG TRUE) -find_package(Threads) -target_link_libraries(ocre_bash PRIVATE Threads::Threads) diff --git a/src/samples/bash_runtime/posix/bash/CMakeLists.txt b/src/samples/bash_runtime/posix/bash/CMakeLists.txt deleted file mode 100644 index 67abe87a..00000000 --- a/src/samples/bash_runtime/posix/bash/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -cmake_minimum_required(VERSION 3.20.0) - -set(OCRE_DEFAULT_WORKING_DIRECTORY "/var/lib/ocre") - -add_library(OcreRuntimeBash) - -target_sources(OcreRuntimeBash PRIVATE - bash.c -) - -target_include_directories(OcreRuntimeBash PUBLIC - include -) - -target_link_libraries(OcreRuntimeBash PUBLIC - OcrePlatform - OcreRuntime -) diff --git a/src/samples/bash_runtime/posix/bash/bash.c b/src/samples/bash_runtime/posix/bash/bash.c deleted file mode 100644 index 58f6acef..00000000 --- a/src/samples/bash_runtime/posix/bash/bash.c +++ /dev/null @@ -1,182 +0,0 @@ -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include - -#include - -LOG_MODULE_REGISTER(bash_runtime, CONFIG_OCRE_LOG_LEVEL); - -struct bash_context { - pid_t pid; - char **argv; - char **envp; -}; - -static int instance_execute(void *runtime_context) -{ - struct bash_context *context = runtime_context; - - // TODO: configure fileactions and attr - - int ret; - ret = posix_spawnp(&context->pid, "/bin/bash", NULL, NULL, context->argv, context->envp); - - if (ret) { - LOG_ERR("Failed to spawn process ret=%d errno=%d", ret, errno); - return -1; - } - - LOG_INF("Process spawned successfully PID=%d", context->pid); - - int status; - - pid_t pid = waitpid(context->pid, &status, 0); - if (pid == -1) { - LOG_ERR("Failed to wait for process"); - return -1; - } - - LOG_INF("Waitpid returned %d status: %d", pid, WEXITSTATUS(status)); - - LOG_INF("Container %p completed successfully", context); - - return WEXITSTATUS(status); -} - -static int instance_thread_execute(void *arg) -{ - struct bash_context *context = arg; - - int ret = instance_execute(context); - - return ret; -} - -static void *instance_create(const char *img_path, const char *workdir, size_t stack_size, size_t heap_size, const char **capabilities, - const char **argv, const char **envp, const char **mounts) -{ - if (!img_path) { - LOG_ERR("Invalid arguments"); - return NULL; - } - - struct bash_context *context = malloc(sizeof(struct bash_context)); - if (!context) { - LOG_ERR("Failed to allocate memory for BASH container size=%zu errno=%d", sizeof(struct bash_context), - errno); - return NULL; - } - - memset(context, 0, sizeof(struct bash_context)); - - for (const char **cap = capabilities; cap && *cap; cap++) { - LOG_WRN("Capability '%s' not supported by runtime", *cap); - } - - // For envp we can just keep a reference - // as the container is guaranteed to only free it after our lifetime - context->envp = (char **)envp; - - // We need to insert argv[0] and argv[1]. We can keep a shallow copy, because - // the container is guaranteed to only free it after our lifetime - int argc = 0; - while (argv && argv[argc]) { - argc++; - } - - // 3 more: bash, script name and NULL - context->argv = malloc(sizeof(char *) * (argc + 3)); - if (!context->argv) { - LOG_ERR("Failed to allocate memory for argv"); - goto error_context; - } - - memset(context->argv, 0, sizeof(char *) * (argc + 3)); - - context->argv[0] = strdup("/bin/bash"); - if (!context->argv[0]) { - goto error_argv; - } - - context->argv[1] = strdup(img_path); - if (!context->argv[1]) { - goto error_argv; - } - - int i; - for (i = 0; i < argc; i++) { - context->argv[i + 2] = strdup(argv[i]); - if (!context->argv[i + 2]) { - goto error_argv; - } - } - - context->argv[i + 2] = NULL; - - return context; - - // TODO: set up chroot, namespace, jails, whatever - // configure fileactions here instead? - -error_argv: - free(context->argv[0]); - free(context->argv[1]); - free(context->argv); - -error_context: - free(context); - - return NULL; -} - -static int instance_kill(void *runtime_context) -{ - struct bash_context *context = runtime_context; - - if (!context) { - return -1; - } - - int rc = kill(context->pid, SIGKILL); - if (rc < 0) { - LOG_ERR("Failed to kill process: rc=%d, errno=%d", rc, errno); - return -1; - } - - return 0; -} - -static int instance_destroy(void *runtime_context) -{ - struct bash_context *context = runtime_context; - - if (!context) { - return -1; - } - - free(context->argv[0]); - free(context->argv[1]); - free(context->argv); - - free(context); - - return 0; -} - -const struct ocre_runtime_vtable bash_vtable = { - .runtime_name = "bash", - .create = instance_create, - .destroy = instance_destroy, - .thread_execute = instance_thread_execute, - .kill = instance_kill, -}; diff --git a/src/samples/bash_runtime/posix/bash/include/ocre/runtime/bash/bash.h b/src/samples/bash_runtime/posix/bash/include/ocre/runtime/bash/bash.h deleted file mode 100644 index f2400918..00000000 --- a/src/samples/bash_runtime/posix/bash/include/ocre/runtime/bash/bash.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef OCRE_RUNTIME_BASH_H -#define OCRE_RUNTIME_BASH_H - -#include - -extern const struct ocre_runtime_vtable bash_vtable; - -#endif /* OCRE_RUNTIME_BASH_H */ diff --git a/src/samples/bash_runtime/posix/main.c b/src/samples/bash_runtime/posix/main.c deleted file mode 100644 index 86a08e61..00000000 --- a/src/samples/bash_runtime/posix/main.c +++ /dev/null @@ -1,87 +0,0 @@ -#include -#include - -#include - -#include -#include - -#include "../../ocre/container.h" - -#define OCRE_DEFAULT_WORKING_DIRECTORY "./var/lib/ocre" - -int main(int argc, char *argv[]) -{ - int rc; - - rc = ocre_initialize(); - if (rc) { - fprintf(stderr, "Failed to initialize OCRE\n"); - return 1; - } - - rc = ocre_initialize_with_runtimes((const struct ocre_runtime_vtable *const[]){&bash_vtable, NULL}); - if (rc) { - fprintf(stderr, "Failed to initialize runtimes\n"); - return 1; - } - - struct ocre_context *ocre = ocre_create_context(OCRE_DEFAULT_WORKING_DIRECTORY); - if (!ocre) { - fprintf(stderr, "Failed to create ocre context\n"); - return 1; - } - - struct ocre_container_args args = { - .argv = (const char *[]){"teste", "dois", NULL}, - .envp = (const char *[]){"VAR=variable", "VAR2=variable2", NULL}, - }; - - struct ocre_container *wasm_container = - ocre_context_create_container(ocre, "blinky", "wamr", NULL, false, &args); - if (!wasm_container) { - fprintf(stderr, "Failed to create WASM container\n"); - return 1; - } - - struct ocre_container *bash_container = - ocre_context_create_container(ocre, "atym.sh", "bash", "my_bash", true, &args); - if (!bash_container) { - fprintf(stderr, "Failed to create bash container\n"); - return 1; - } - - fprintf(stderr, "Will start WAMR container\n"); - - rc = ocre_container_start(wasm_container); - if (rc) { - fprintf(stderr, "Failed to start WASM container\n"); - return 1; - } - - fprintf(stderr, "Will start bash container\n"); - - rc = ocre_container_start(bash_container); - if (rc) { - fprintf(stderr, "Failed to start bash container\n"); - return 1; - } - - int exit_code; - - if (ocre_container_wait(bash_container, &exit_code)) { - fprintf(stderr, "Failed to wait for bash container\n"); - return 1; - } - - fprintf(stderr, "Bash container exited with status %d\n", exit_code); - - if (ocre_container_wait(wasm_container, &exit_code)) { - fprintf(stderr, "Failed to wait for WASM container\n"); - return 1; - } - - fprintf(stderr, "WASM container exited with status %d\n", exit_code); - - return 0; -} From 82533da2c6106d8f17e7f59282dc91d1fef52c6d Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 11:05:42 +0100 Subject: [PATCH 158/234] fix(shell/create): fix some error print line endings Signed-off-by: Marco Casaroli --- src/shell/container/create.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/shell/container/create.c b/src/shell/container/create.c index 18bcd27a..9e2b0e9a 100644 --- a/src/shell/container/create.c +++ b/src/shell/container/create.c @@ -101,26 +101,29 @@ int cmd_container_create_run(struct ocre_context *ctx, char *argv0, int argc, ch */ if (optarg[0] != '/') { - fprintf(stderr, "Invalid mount format: '%s': source must be absolute path", optarg); + fprintf(stderr, "Invalid mount format: '%s': source must be absolute path\n", + optarg); goto cleanup; } char *dst = strchr(optarg, ':'); if (!dst) { - fprintf(stderr, "Invalid mount format: '%s': must be :", optarg); + fprintf(stderr, "Invalid mount format: '%s': must be :\n", + optarg); goto cleanup; } dst++; if (dst[0] != '/') { - fprintf(stderr, "Invalid mount format: '%s': destination must be absolute path", + fprintf(stderr, "Invalid mount format: '%s': destination must be absolute path\n", optarg); goto cleanup; } if (dst[1] == '\0') { - fprintf(stderr, "Invalid mount format: '%s': destination must not be '/'", optarg); + fprintf(stderr, "Invalid mount format: '%s': destination must not be '/'\n", + optarg); goto cleanup; } From cd77bd00d8d305e2e040f9d06ef5b09213b4dcfd Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 11:12:19 +0100 Subject: [PATCH 159/234] chore: clang-format Signed-off-by: Marco Casaroli --- src/ocre/ocre.c | 2 +- src/ocre/util/rm_rf.c | 323 ++--- src/platform/posix/file_mmap.c | 6 +- .../posix/include/ocre/platform/log.h | 42 +- .../wamr/ocre_api/ocre_gpio/ocre_gpio.c | 1161 +++++++++-------- .../wamr/ocre_api/ocre_gpio/ocre_gpio.h | 22 +- .../wamr/ocre_api/ocre_sensors/ocre_sensors.c | 444 ++++--- .../wamr/ocre_api/ocre_sensors/ocre_sensors.h | 26 +- .../wamr/ocre_api/ocre_sensors/rng_sensor.c | 49 +- src/samples/demo/main.c | 1 - src/samples/mini/main.c | 7 +- src/samples/supervisor/zephyr/download_file.c | 8 +- src/shell/container/create.c | 3 +- src/shell/container/kill.c | 24 +- src/shell/container/ps.c | 24 +- src/shell/container/start.c | 28 +- src/shell/container/wait.c | 44 +- src/shell/sha256/sha256.c | 273 ++-- src/shell/sha256/sha256.h | 60 +- 19 files changed, 1306 insertions(+), 1241 deletions(-) diff --git a/src/ocre/ocre.c b/src/ocre/ocre.c index 9650efe2..4af06ee5 100644 --- a/src/ocre/ocre.c +++ b/src/ocre/ocre.c @@ -38,7 +38,7 @@ static struct runtime_node *runtimes = NULL; int ocre_initialize(const struct ocre_runtime_vtable *const vtable[]) { - LOG_INF("Initializing Ocre %s", ocre_build_configuration.version); + LOG_INF("Initializing Ocre %s", ocre_build_configuration.version); LOG_INF("Build Commit ID: %s", ocre_build_configuration.commit_id); LOG_INF("Build Info: %s", ocre_build_configuration.build_info); LOG_INF("Build Date: %s", ocre_build_configuration.build_date); diff --git a/src/ocre/util/rm_rf.c b/src/ocre/util/rm_rf.c index abec6023..d91ca627 100644 --- a/src/ocre/util/rm_rf.c +++ b/src/ocre/util/rm_rf.c @@ -9,169 +9,192 @@ /* AI generated code: please don't joke */ /* Stack node for directory traversal */ + struct dir_stack_node { - char *path; - DIR *dir; - int is_removal_phase; - struct dir_stack_node *next; + char *path; + DIR *dir; + int is_removal_phase; + struct dir_stack_node *next; }; /* Stack operations */ -static struct dir_stack_node* push_dir(struct dir_stack_node *stack, const char *path, int is_removal_phase) { - struct dir_stack_node *node = malloc(sizeof(struct dir_stack_node)); - if (!node) { - return NULL; - } - - node->path = strdup(path); - if (!node->path) { - free(node); - return NULL; - } - - node->dir = NULL; - node->is_removal_phase = is_removal_phase; - node->next = stack; - - return node; + +static struct dir_stack_node *push_dir(struct dir_stack_node *stack, const char *path, int is_removal_phase) +{ + struct dir_stack_node *node = malloc(sizeof(struct dir_stack_node)); + if (!node) { + return NULL; + } + + node->path = strdup(path); + if (!node->path) { + free(node); + return NULL; + } + + node->dir = NULL; + node->is_removal_phase = is_removal_phase; + node->next = stack; + + return node; } -static struct dir_stack_node* pop_dir(struct dir_stack_node *stack) { - if (!stack) { - return NULL; - } +static struct dir_stack_node *pop_dir(struct dir_stack_node *stack) +{ + if (!stack) { + return NULL; + } - struct dir_stack_node *next = stack->next; + struct dir_stack_node *next = stack->next; - if (stack->dir) { - closedir(stack->dir); - } - free(stack->path); - free(stack); + if (stack->dir) { + closedir(stack->dir); + } + free(stack->path); + free(stack); - return next; + return next; } /* Build full path by concatenating directory and filename */ -static char* build_path(const char *dir, const char *name) { - size_t dir_len = strlen(dir); - size_t name_len = strlen(name); - size_t total_len = dir_len + name_len + 2; /* +1 for '/', +1 for '\0' */ - - char *path = malloc(total_len); - if (!path) { - return NULL; - } - - snprintf(path, total_len, "%s/%s", dir, name); - return path; + +static char *build_path(const char *dir, const char *name) +{ + size_t dir_len = strlen(dir); + size_t name_len = strlen(name); + size_t total_len = dir_len + name_len + 2; /* +1 for '/', +1 for '\0' */ + + char *path = malloc(total_len); + if (!path) { + return NULL; + } + + snprintf(path, total_len, "%s/%s", dir, name); + return path; } /* Remove directory recursively using stack-based traversal (no function recursion) */ -int rm_rf(const char *path) { - if (!path) { - errno = EINVAL; - return -1; - } - - struct stat st; - if (stat(path, &st) == -1) { - return -1; /* errno already set by stat */ - } - - /* If it's a regular file, just remove it */ - if (!S_ISDIR(st.st_mode)) { - return unlink(path); - } - - /* Stack for directory traversal */ - struct dir_stack_node *stack = NULL; - int result = 0; - - /* Push initial directory onto stack */ - stack = push_dir(stack, path, 0); - if (!stack) { - errno = ENOMEM; - return -1; - } - - /* Process stack until empty */ - while (stack) { - struct dir_stack_node *current = stack; - - if (current->is_removal_phase) { - /* This directory has been processed, now remove it */ - if (rmdir(current->path) == -1) { - result = -1; - /* Continue processing to clean up stack */ - } - stack = pop_dir(stack); - continue; - } - - /* First time processing this directory */ - if (!current->dir) { - current->dir = opendir(current->path); - if (!current->dir) { - result = -1; - stack = pop_dir(stack); - continue; - } - } - - /* Read next directory entry */ - struct dirent *entry = readdir(current->dir); - if (!entry) { - /* No more entries, mark for removal and continue */ - current->is_removal_phase = 1; - continue; - } - - /* Skip . and .. entries */ - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { - continue; - } - - /* Build full path for this entry */ - char *entry_path = build_path(current->path, entry->d_name); - if (!entry_path) { - result = -1; - errno = ENOMEM; - break; - } - - /* Get entry information */ - if (stat(entry_path, &st) == -1) { - result = -1; - free(entry_path); - continue; - } - - if (S_ISDIR(st.st_mode)) { - /* It's a directory - push it onto stack for processing */ - struct dir_stack_node *new_node = push_dir(stack, entry_path, 0); - if (!new_node) { - result = -1; - errno = ENOMEM; - free(entry_path); - break; - } - stack = new_node; - } else { - /* It's a file - remove it directly */ - if (unlink(entry_path) == -1) { - result = -1; - /* Continue processing other entries */ - } - } - - free(entry_path); - } - - /* Clean up remaining stack in case of error */ - while (stack) { - stack = pop_dir(stack); - } - - return result; + +int rm_rf(const char *path) +{ + if (!path) { + errno = EINVAL; + return -1; + } + + struct stat st; + if (stat(path, &st) == -1) { + return -1; /* errno already set by stat */ + } + + /* If it's a regular file, just remove it */ + + if (!S_ISDIR(st.st_mode)) { + return unlink(path); + } + + /* Stack for directory traversal */ + + struct dir_stack_node *stack = NULL; + int result = 0; + + /* Push initial directory onto stack */ + + stack = push_dir(stack, path, 0); + if (!stack) { + errno = ENOMEM; + return -1; + } + + /* Process stack until empty */ + + while (stack) { + struct dir_stack_node *current = stack; + + if (current->is_removal_phase) { + /* This directory has been processed, now remove it */ + + if (rmdir(current->path) == -1) { + result = -1; + + /* Continue processing to clean up stack */ + } + stack = pop_dir(stack); + continue; + } + + /* First time processing this directory */ + + if (!current->dir) { + current->dir = opendir(current->path); + if (!current->dir) { + result = -1; + stack = pop_dir(stack); + continue; + } + } + + /* Read next directory entry */ + + struct dirent *entry = readdir(current->dir); + if (!entry) { + /* No more entries, mark for removal and continue */ + current->is_removal_phase = 1; + continue; + } + + /* Skip . and .. entries */ + + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { + continue; + } + + /* Build full path for this entry */ + + char *entry_path = build_path(current->path, entry->d_name); + if (!entry_path) { + result = -1; + errno = ENOMEM; + break; + } + + /* Get entry information */ + + if (stat(entry_path, &st) == -1) { + result = -1; + free(entry_path); + continue; + } + + if (S_ISDIR(st.st_mode)) { + /* It's a directory - push it onto stack for processing */ + + struct dir_stack_node *new_node = push_dir(stack, entry_path, 0); + if (!new_node) { + result = -1; + errno = ENOMEM; + free(entry_path); + break; + } + stack = new_node; + } else { + /* It's a file - remove it directly */ + + if (unlink(entry_path) == -1) { + result = -1; + + /* Continue processing other entries */ + } + } + + free(entry_path); + } + + /* Clean up remaining stack in case of error */ + + while (stack) { + stack = pop_dir(stack); + } + + return result; } diff --git a/src/platform/posix/file_mmap.c b/src/platform/posix/file_mmap.c index ea1bad8d..384a01ad 100644 --- a/src/platform/posix/file_mmap.c +++ b/src/platform/posix/file_mmap.c @@ -78,9 +78,9 @@ void *ocre_load_file(const char *path, size_t *size) int ocre_unload_file(void *buffer, size_t size) { - if (!buffer) { - return 0; - } + if (!buffer) { + return 0; + } if (munmap(buffer, size)) { int save_errno = errno; diff --git a/src/platform/posix/include/ocre/platform/log.h b/src/platform/posix/include/ocre/platform/log.h index 69197498..e0a3f16d 100644 --- a/src/platform/posix/include/ocre/platform/log.h +++ b/src/platform/posix/include/ocre/platform/log.h @@ -3,30 +3,54 @@ #include "config.h" #define LOG_MODULE_REGISTER(module, ...) static const char *const __ocre_log_module = #module -#define LOG_MODULE_DECLARE(module, ...) static const char *const __ocre_log_module = #module +#define LOG_MODULE_DECLARE(module, ...) static const char *const __ocre_log_module = #module extern int __ocre_log_level; #if CONFIG_OCRE_LOG_LEVEL >= 1 -#define LOG_ERR(fmt, ...) do { if (__ocre_log_level >= 1) fprintf(stderr, " %s: " fmt "\n", __ocre_log_module, ##__VA_ARGS__); } while (0) +#define LOG_ERR(fmt, ...) \ + do { \ + if (__ocre_log_level >= 1) \ + fprintf(stderr, " %s: " fmt "\n", __ocre_log_module, ##__VA_ARGS__); \ + } while (0) #else -#define LOG_ERR(fmt, ...) do {} while (0) +#define LOG_ERR(fmt, ...) \ + do { \ + } while (0) #endif #if CONFIG_OCRE_LOG_LEVEL >= 2 -#define LOG_WRN(fmt, ...) do { if (__ocre_log_level >= 2) fprintf(stderr, " %s: " fmt "\n", __ocre_log_module, ##__VA_ARGS__); } while (0) +#define LOG_WRN(fmt, ...) \ + do { \ + if (__ocre_log_level >= 2) \ + fprintf(stderr, " %s: " fmt "\n", __ocre_log_module, ##__VA_ARGS__); \ + } while (0) #else -#define LOG_WRN(fmt, ...) do {} while (0) +#define LOG_WRN(fmt, ...) \ + do { \ + } while (0) #endif #if CONFIG_OCRE_LOG_LEVEL >= 3 -#define LOG_INF(fmt, ...) do { if (__ocre_log_level >= 3) fprintf(stderr, " %s: " fmt "\n", __ocre_log_module, ##__VA_ARGS__); } while (0) +#define LOG_INF(fmt, ...) \ + do { \ + if (__ocre_log_level >= 3) \ + fprintf(stderr, " %s: " fmt "\n", __ocre_log_module, ##__VA_ARGS__); \ + } while (0) #else -#define LOG_INF(fmt, ...) do {} while (0) +#define LOG_INF(fmt, ...) \ + do { \ + } while (0) #endif #if CONFIG_OCRE_LOG_LEVEL >= 4 -#define LOG_DBG(fmt, ...) do { if (__ocre_log_level >= 4) fprintf(stderr, " %s: " fmt "\n", __ocre_log_module, ##__VA_ARGS__); } while (0) +#define LOG_DBG(fmt, ...) \ + do { \ + if (__ocre_log_level >= 4) \ + fprintf(stderr, " %s: " fmt "\n", __ocre_log_module, ##__VA_ARGS__); \ + } while (0) #else -#define LOG_DBG(fmt, ...) do {} while (0) +#define LOG_DBG(fmt, ...) \ + do { \ + } while (0) #endif diff --git a/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.c b/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.c index 84bd8c01..214720a4 100644 --- a/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.c +++ b/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.c @@ -17,675 +17,712 @@ LOG_MODULE_REGISTER(ocre_gpio, CONFIG_OCRE_LOG_LEVEL); typedef struct { - uint32_t in_use: 1; - uint32_t direction: 1; - uint32_t pin_number: 6; - uint32_t port_idx: 4; - struct gpio_callback *cb; - wasm_module_inst_t owner; + uint32_t in_use : 1; + uint32_t direction : 1; + uint32_t pin_number : 6; + uint32_t port_idx : 4; + struct gpio_callback *cb; + wasm_module_inst_t owner; } gpio_pin_ocre; typedef struct { - const char *name; - const struct device *port; - gpio_pin_t pin; - int port_idx; + const char *name; + const struct device *port; + gpio_pin_t pin; + int port_idx; } gpio_alias_t; static gpio_alias_t gpio_aliases[CONFIG_OCRE_GPIO_MAX_PINS]; static int gpio_alias_count = 0; - static gpio_pin_ocre gpio_pins[CONFIG_OCRE_GPIO_MAX_PINS]; static const struct device *gpio_ports[CONFIG_OCRE_GPIO_MAX_PORTS]; static bool port_ready[CONFIG_OCRE_GPIO_MAX_PORTS]; static bool gpio_system_initialized = false; -#define INIT_GPIO_PORT_NAMED(idx, label, name_str) \ - do { \ - if (DT_NODE_EXISTS(label)) { \ - gpio_ports[idx] = DEVICE_DT_GET(label); \ - if (!device_is_ready(gpio_ports[idx])) { \ - LOG_ERR("%s not ready", name_str); \ - } else { \ - LOG_DBG("%s initialized", name_str); \ - port_ready[idx] = true; \ - port_count++; \ - } \ - } \ - } while (0) +#define INIT_GPIO_PORT_NAMED(idx, label, name_str) \ + do { \ + if (DT_NODE_EXISTS(label)) { \ + gpio_ports[idx] = DEVICE_DT_GET(label); \ + if (!device_is_ready(gpio_ports[idx])) { \ + LOG_ERR("%s not ready", name_str); \ + } else { \ + LOG_DBG("%s initialized", name_str); \ + port_ready[idx] = true; \ + port_count++; \ + } \ + } \ + } while (0) static void gpio_callback_handler(const struct device *port, struct gpio_callback *cb, gpio_port_pins_t pins); -int ocre_gpio_init(void) { - if (gpio_system_initialized) { - LOG_INF("GPIO system already initialized"); - return 0; - } - if (!common_initialized && ocre_common_init() != 0) { - LOG_ERR("Failed to initialize common subsystem"); - return -EINVAL; - } - int port_count = 0; - memset(port_ready, 0, sizeof(port_ready)); +int ocre_gpio_init(void) +{ + if (gpio_system_initialized) { + LOG_INF("GPIO system already initialized"); + return 0; + } + if (!common_initialized && ocre_common_init() != 0) { + LOG_ERR("Failed to initialize common subsystem"); + return -EINVAL; + } + int port_count = 0; + memset(port_ready, 0, sizeof(port_ready)); #if defined(CONFIG_BOARD_B_U585I_IOT02A) - INIT_GPIO_PORT_NAMED(0, DT_NODELABEL(gpioa), "GPIOA"); - INIT_GPIO_PORT_NAMED(1, DT_NODELABEL(gpiob), "GPIOB"); - INIT_GPIO_PORT_NAMED(2, DT_NODELABEL(gpioc), "GPIOC"); - INIT_GPIO_PORT_NAMED(3, DT_NODELABEL(gpiod), "GPIOD"); - INIT_GPIO_PORT_NAMED(4, DT_NODELABEL(gpioe), "GPIOE"); - INIT_GPIO_PORT_NAMED(5, DT_NODELABEL(gpiof), "GPIOF"); - INIT_GPIO_PORT_NAMED(6, DT_NODELABEL(gpiog), "GPIOG"); - INIT_GPIO_PORT_NAMED(7, DT_NODELABEL(gpioh), "GPIOH"); + INIT_GPIO_PORT_NAMED(0, DT_NODELABEL(gpioa), "GPIOA"); + INIT_GPIO_PORT_NAMED(1, DT_NODELABEL(gpiob), "GPIOB"); + INIT_GPIO_PORT_NAMED(2, DT_NODELABEL(gpioc), "GPIOC"); + INIT_GPIO_PORT_NAMED(3, DT_NODELABEL(gpiod), "GPIOD"); + INIT_GPIO_PORT_NAMED(4, DT_NODELABEL(gpioe), "GPIOE"); + INIT_GPIO_PORT_NAMED(5, DT_NODELABEL(gpiof), "GPIOF"); + INIT_GPIO_PORT_NAMED(6, DT_NODELABEL(gpiog), "GPIOG"); + INIT_GPIO_PORT_NAMED(7, DT_NODELABEL(gpioh), "GPIOH"); #elif defined(CONFIG_BOARD_ESP32C3_DEVKITM) - INIT_GPIO_PORT_NAMED(0, DT_NODELABEL(gpio0), "GPIO0"); + INIT_GPIO_PORT_NAMED(0, DT_NODELABEL(gpio0), "GPIO0"); #elif defined(CONFIG_BOARD_MAX32690EVKIT) - INIT_GPIO_PORT_NAMED(0, DT_NODELABEL(gpio0), "GPIO0"); - INIT_GPIO_PORT_NAMED(1, DT_NODELABEL(gpio1), "GPIO1"); - INIT_GPIO_PORT_NAMED(2, DT_NODELABEL(gpio2), "GPIO2"); - INIT_GPIO_PORT_NAMED(3, DT_NODELABEL(gpio3), "GPIO3"); - INIT_GPIO_PORT_NAMED(4, DT_NODELABEL(gpio4), "GPIO4"); + INIT_GPIO_PORT_NAMED(0, DT_NODELABEL(gpio0), "GPIO0"); + INIT_GPIO_PORT_NAMED(1, DT_NODELABEL(gpio1), "GPIO1"); + INIT_GPIO_PORT_NAMED(2, DT_NODELABEL(gpio2), "GPIO2"); + INIT_GPIO_PORT_NAMED(3, DT_NODELABEL(gpio3), "GPIO3"); + INIT_GPIO_PORT_NAMED(4, DT_NODELABEL(gpio4), "GPIO4"); #elif defined(CONFIG_BOARD_ARDUINO_PORTENTA_H7) - INIT_GPIO_PORT_NAMED(0, DT_NODELABEL(gpioa), "GPIOA"); - INIT_GPIO_PORT_NAMED(1, DT_NODELABEL(gpiob), "GPIOB"); - INIT_GPIO_PORT_NAMED(2, DT_NODELABEL(gpioc), "GPIOC"); - INIT_GPIO_PORT_NAMED(3, DT_NODELABEL(gpiod), "GPIOD"); - INIT_GPIO_PORT_NAMED(4, DT_NODELABEL(gpioe), "GPIOE"); - INIT_GPIO_PORT_NAMED(5, DT_NODELABEL(gpiof), "GPIOF"); - INIT_GPIO_PORT_NAMED(6, DT_NODELABEL(gpiog), "GPIOG"); - INIT_GPIO_PORT_NAMED(7, DT_NODELABEL(gpioh), "GPIOH"); - INIT_GPIO_PORT_NAMED(8, DT_NODELABEL(gpioi), "GPIOI"); - INIT_GPIO_PORT_NAMED(9, DT_NODELABEL(gpioj), "GPIOJ"); - INIT_GPIO_PORT_NAMED(10, DT_NODELABEL(gpiok), "GPIOK"); + INIT_GPIO_PORT_NAMED(0, DT_NODELABEL(gpioa), "GPIOA"); + INIT_GPIO_PORT_NAMED(1, DT_NODELABEL(gpiob), "GPIOB"); + INIT_GPIO_PORT_NAMED(2, DT_NODELABEL(gpioc), "GPIOC"); + INIT_GPIO_PORT_NAMED(3, DT_NODELABEL(gpiod), "GPIOD"); + INIT_GPIO_PORT_NAMED(4, DT_NODELABEL(gpioe), "GPIOE"); + INIT_GPIO_PORT_NAMED(5, DT_NODELABEL(gpiof), "GPIOF"); + INIT_GPIO_PORT_NAMED(6, DT_NODELABEL(gpiog), "GPIOG"); + INIT_GPIO_PORT_NAMED(7, DT_NODELABEL(gpioh), "GPIOH"); + INIT_GPIO_PORT_NAMED(8, DT_NODELABEL(gpioi), "GPIOI"); + INIT_GPIO_PORT_NAMED(9, DT_NODELABEL(gpioj), "GPIOJ"); + INIT_GPIO_PORT_NAMED(10, DT_NODELABEL(gpiok), "GPIOK"); #elif defined(CONFIG_BOARD_W5500_EVB_PICO2) - INIT_GPIO_PORT_NAMED(0, DT_NODELABEL(gpio0), "GPIO0"); + INIT_GPIO_PORT_NAMED(0, DT_NODELABEL(gpio0), "GPIO0"); + +#elif defined(CONFIG_BOARD_MIMXRT1064_EVK) + // No gpio0 for some reason? Will be annoying for some APIs + INIT_GPIO_PORT_NAMED(0, DT_NODELABEL(gpio1), "GPIO1"); + INIT_GPIO_PORT_NAMED(1, DT_NODELABEL(gpio2), "GPIO2"); + INIT_GPIO_PORT_NAMED(2, DT_NODELABEL(gpio3), "GPIO3"); + INIT_GPIO_PORT_NAMED(3, DT_NODELABEL(gpio4), "GPIO4"); + INIT_GPIO_PORT_NAMED(4, DT_NODELABEL(gpio5), "GPIO5"); + INIT_GPIO_PORT_NAMED(5, DT_NODELABEL(gpio6), "GPIO6"); + INIT_GPIO_PORT_NAMED(6, DT_NODELABEL(gpio7), "GPIO7"); + INIT_GPIO_PORT_NAMED(7, DT_NODELABEL(gpio8), "GPIO8"); + INIT_GPIO_PORT_NAMED(8, DT_NODELABEL(gpio9), "GPIO9"); #else - // Generic fallback + // Generic fallback #if DT_NODE_EXISTS(DT_NODELABEL(gpio0)) - INIT_GPIO_PORT_NAMED(0, DT_NODELABEL(gpio0), "GPIO0"); + INIT_GPIO_PORT_NAMED(0, DT_NODELABEL(gpio0), "GPIO0"); #elif DT_NODE_EXISTS(DT_NODELABEL(gpioa)) - INIT_GPIO_PORT_NAMED(0, DT_NODELABEL(gpioa), "GPIOA"); + INIT_GPIO_PORT_NAMED(0, DT_NODELABEL(gpioa), "GPIOA"); #endif #endif - if (port_count == 0) { - LOG_ERR("No GPIO ports were initialized"); - return -ENODEV; - } - ocre_register_cleanup_handler(OCRE_RESOURCE_TYPE_GPIO, ocre_gpio_cleanup_container); - gpio_system_initialized = true; - LOG_INF("GPIO system initialized, %d ports available", port_count); - return 0; + if (port_count == 0) { + LOG_ERR("No GPIO ports were initialized"); + return -ENODEV; + } + ocre_register_cleanup_handler(OCRE_RESOURCE_TYPE_GPIO, ocre_gpio_cleanup_container); + gpio_system_initialized = true; + LOG_INF("GPIO system initialized, %d ports available", port_count); + return 0; } -int ocre_gpio_configure(const ocre_gpio_config_t *config) { - if (!gpio_system_initialized || !config || config->pin >= CONFIG_OCRE_GPIO_PINS_PER_PORT || - config->port_idx >= CONFIG_OCRE_GPIO_MAX_PORTS || !port_ready[config->port_idx]) { - LOG_ERR("Invalid GPIO config: port=%d, pin=%d, port_ready=%d", config ? config->port_idx : -1, - config ? config->pin : -1, config ? port_ready[config->port_idx] : false); - return -EINVAL; - } - int port_idx = config->port_idx; - gpio_pin_t pin = config->pin; - gpio_flags_t flags = (config->direction == OCRE_GPIO_DIR_INPUT) ? GPIO_INPUT : GPIO_OUTPUT; - if (config->direction == OCRE_GPIO_DIR_INPUT) { - flags |= GPIO_PULL_UP; - } - int ret = gpio_pin_configure(gpio_ports[port_idx], pin, flags); - if (ret != 0) { - LOG_ERR("Failed to configure GPIO pin %d on port %d: %d", pin, port_idx, ret); - return ret; - } - wasm_module_inst_t module_inst = ocre_get_current_module(); - if (!module_inst) { - LOG_ERR("No current module instance for GPIO configuration"); - return -EINVAL; - } - int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; - if (global_pin >= CONFIG_OCRE_GPIO_MAX_PINS) { - LOG_ERR("Global pin %d exceeds max %d", global_pin, CONFIG_OCRE_GPIO_MAX_PINS); - return -EINVAL; - } - gpio_pins[global_pin] = (gpio_pin_ocre){.in_use = 1, - .direction = (config->direction == OCRE_GPIO_DIR_OUTPUT), - .pin_number = pin, - .port_idx = port_idx, - .cb = NULL, - .owner = module_inst}; - ocre_increment_resource_count(module_inst, OCRE_RESOURCE_TYPE_GPIO); - LOG_INF("Configured GPIO pin %d on port %d (global %d) for module %p", pin, port_idx, global_pin, - (void *)module_inst); - return 0; +int ocre_gpio_configure(const ocre_gpio_config_t *config) +{ + if (!gpio_system_initialized || !config || config->pin >= CONFIG_OCRE_GPIO_PINS_PER_PORT || + config->port_idx >= CONFIG_OCRE_GPIO_MAX_PORTS || !port_ready[config->port_idx]) { + LOG_ERR("Invalid GPIO config: port=%d, pin=%d, port_ready=%d", config ? config->port_idx : -1, + config ? config->pin : -1, config ? port_ready[config->port_idx] : false); + return -EINVAL; + } + int port_idx = config->port_idx; + gpio_pin_t pin = config->pin; + gpio_flags_t flags = (config->direction == OCRE_GPIO_DIR_INPUT) ? GPIO_INPUT : GPIO_OUTPUT; + if (config->direction == OCRE_GPIO_DIR_INPUT) { + flags |= GPIO_PULL_UP; + } + int ret = gpio_pin_configure(gpio_ports[port_idx], pin, flags); + if (ret != 0) { + LOG_ERR("Failed to configure GPIO pin %d on port %d: %d", pin, port_idx, ret); + return ret; + } + wasm_module_inst_t module_inst = ocre_get_current_module(); + if (!module_inst) { + LOG_ERR("No current module instance for GPIO configuration"); + return -EINVAL; + } + int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; + if (global_pin >= CONFIG_OCRE_GPIO_MAX_PINS) { + LOG_ERR("Global pin %d exceeds max %d", global_pin, CONFIG_OCRE_GPIO_MAX_PINS); + return -EINVAL; + } + gpio_pins[global_pin] = (gpio_pin_ocre){.in_use = 1, + .direction = (config->direction == OCRE_GPIO_DIR_OUTPUT), + .pin_number = pin, + .port_idx = port_idx, + .cb = NULL, + .owner = module_inst}; + ocre_increment_resource_count(module_inst, OCRE_RESOURCE_TYPE_GPIO); + LOG_INF("Configured GPIO pin %d on port %d (global %d) for module %p", pin, port_idx, global_pin, + (void *)module_inst); + return 0; } -int ocre_gpio_pin_set(int pin, ocre_gpio_pin_state_t state) { - if (pin >= CONFIG_OCRE_GPIO_MAX_PINS || !gpio_pins[pin].in_use || gpio_pins[pin].direction != 1 || - !port_ready[gpio_pins[pin].port_idx]) { - LOG_ERR("Invalid GPIO pin %d or not configured as output or port not ready", pin); - return -EINVAL; - } - int ret = gpio_pin_set(gpio_ports[gpio_pins[pin].port_idx], gpio_pins[pin].pin_number, state); - if (ret != 0) { - LOG_ERR("Failed to set GPIO pin %d: %d", pin, ret); - } - return ret; +int ocre_gpio_pin_set(int pin, ocre_gpio_pin_state_t state) +{ + if (pin >= CONFIG_OCRE_GPIO_MAX_PINS || !gpio_pins[pin].in_use || gpio_pins[pin].direction != 1 || + !port_ready[gpio_pins[pin].port_idx]) { + LOG_ERR("Invalid GPIO pin %d or not configured as output or port not ready", pin); + return -EINVAL; + } + int ret = gpio_pin_set(gpio_ports[gpio_pins[pin].port_idx], gpio_pins[pin].pin_number, state); + if (ret != 0) { + LOG_ERR("Failed to set GPIO pin %d: %d", pin, ret); + } + return ret; } -ocre_gpio_pin_state_t ocre_gpio_pin_get(int pin) { - if (pin >= CONFIG_OCRE_GPIO_MAX_PINS || !gpio_pins[pin].in_use || !port_ready[gpio_pins[pin].port_idx]) { - LOG_ERR("Invalid or unconfigured GPIO pin %d or port not ready", pin); - return -EINVAL; - } - int value = gpio_pin_get(gpio_ports[gpio_pins[pin].port_idx], gpio_pins[pin].pin_number); - return (value >= 0) ? (value ? OCRE_GPIO_PIN_SET : OCRE_GPIO_PIN_RESET) : value; +ocre_gpio_pin_state_t ocre_gpio_pin_get(int pin) +{ + if (pin >= CONFIG_OCRE_GPIO_MAX_PINS || !gpio_pins[pin].in_use || !port_ready[gpio_pins[pin].port_idx]) { + LOG_ERR("Invalid or unconfigured GPIO pin %d or port not ready", pin); + return -EINVAL; + } + int value = gpio_pin_get(gpio_ports[gpio_pins[pin].port_idx], gpio_pins[pin].pin_number); + return (value >= 0) ? (value ? OCRE_GPIO_PIN_SET : OCRE_GPIO_PIN_RESET) : value; } -int ocre_gpio_pin_toggle(int pin) { - if (pin >= CONFIG_OCRE_GPIO_MAX_PINS || !gpio_pins[pin].in_use || gpio_pins[pin].direction != 1 || - !port_ready[gpio_pins[pin].port_idx]) { - LOG_ERR("Invalid GPIO pin %d or not configured as output or port not ready", pin); - return -EINVAL; - } - int ret = gpio_pin_toggle(gpio_ports[gpio_pins[pin].port_idx], gpio_pins[pin].pin_number); - if (ret != 0) { - LOG_ERR("Failed to toggle GPIO pin %d: %d", pin, ret); - } - return ret; +int ocre_gpio_pin_toggle(int pin) +{ + if (pin >= CONFIG_OCRE_GPIO_MAX_PINS || !gpio_pins[pin].in_use || gpio_pins[pin].direction != 1 || + !port_ready[gpio_pins[pin].port_idx]) { + LOG_ERR("Invalid GPIO pin %d or not configured as output or port not ready", pin); + return -EINVAL; + } + int ret = gpio_pin_toggle(gpio_ports[gpio_pins[pin].port_idx], gpio_pins[pin].pin_number); + if (ret != 0) { + LOG_ERR("Failed to toggle GPIO pin %d: %d", pin, ret); + } + return ret; } -int ocre_gpio_register_callback(int pin) { - if (pin >= CONFIG_OCRE_GPIO_MAX_PINS || !gpio_pins[pin].in_use || gpio_pins[pin].direction != 0 || - !port_ready[gpio_pins[pin].port_idx]) { - LOG_ERR("Invalid GPIO pin %d or not configured as input or port not ready", pin); - return -EINVAL; - } - gpio_pin_ocre *gpio = &gpio_pins[pin]; - if (!gpio->cb) { - gpio->cb = k_calloc(1, sizeof(struct gpio_callback)); - if (!gpio->cb) { - LOG_ERR("Failed to allocate memory for GPIO callback"); - return -ENOMEM; - } - } - int ret = gpio_pin_interrupt_configure(gpio_ports[gpio->port_idx], gpio->pin_number, GPIO_INT_EDGE_BOTH); - if (ret) { - LOG_ERR("Failed to configure interrupt for GPIO pin %d: %d", pin, ret); - k_free(gpio->cb); - gpio->cb = NULL; - return ret; - } - gpio_init_callback(gpio->cb, gpio_callback_handler, BIT(gpio->pin_number)); - ret = gpio_add_callback(gpio_ports[gpio->port_idx], gpio->cb); - if (ret) { - LOG_ERR("Failed to add callback for GPIO pin %d: %d", pin, ret); - k_free(gpio->cb); - gpio->cb = NULL; - return ret; - } - LOG_INF("Registered callback for GPIO pin %d (port %d, pin %d)", pin, gpio->port_idx, gpio->pin_number); - return 0; +int ocre_gpio_register_callback(int pin) +{ + if (pin >= CONFIG_OCRE_GPIO_MAX_PINS || !gpio_pins[pin].in_use || gpio_pins[pin].direction != 0 || + !port_ready[gpio_pins[pin].port_idx]) { + LOG_ERR("Invalid GPIO pin %d or not configured as input or port not ready", pin); + return -EINVAL; + } + gpio_pin_ocre *gpio = &gpio_pins[pin]; + if (!gpio->cb) { + gpio->cb = k_calloc(1, sizeof(struct gpio_callback)); + if (!gpio->cb) { + LOG_ERR("Failed to allocate memory for GPIO callback"); + return -ENOMEM; + } + } + int ret = gpio_pin_interrupt_configure(gpio_ports[gpio->port_idx], gpio->pin_number, GPIO_INT_EDGE_BOTH); + if (ret) { + LOG_ERR("Failed to configure interrupt for GPIO pin %d: %d", pin, ret); + k_free(gpio->cb); + gpio->cb = NULL; + return ret; + } + gpio_init_callback(gpio->cb, gpio_callback_handler, BIT(gpio->pin_number)); + ret = gpio_add_callback(gpio_ports[gpio->port_idx], gpio->cb); + if (ret) { + LOG_ERR("Failed to add callback for GPIO pin %d: %d", pin, ret); + k_free(gpio->cb); + gpio->cb = NULL; + return ret; + } + LOG_INF("Registered callback for GPIO pin %d (port %d, pin %d)", pin, gpio->port_idx, gpio->pin_number); + return 0; } -int ocre_gpio_unregister_callback(int pin) { - if (pin >= CONFIG_OCRE_GPIO_MAX_PINS || !gpio_pins[pin].in_use || !gpio_pins[pin].cb || - !port_ready[gpio_pins[pin].port_idx]) { - LOG_ERR("Invalid GPIO pin %d or no callback registered or port not ready", pin); - return -EINVAL; - } - gpio_pin_ocre *gpio = &gpio_pins[pin]; - int ret = gpio_pin_interrupt_configure(gpio_ports[gpio->port_idx], gpio->pin_number, GPIO_INT_DISABLE); - if (ret) { - LOG_ERR("Failed to disable interrupt for GPIO pin %d: %d", pin, ret); - return ret; - } - ret = gpio_remove_callback(gpio_ports[gpio->port_idx], gpio->cb); - if (ret) { - LOG_ERR("Failed to remove callback for GPIO pin %d: %d", pin, ret); - } - k_free(gpio->cb); - gpio->cb = NULL; - LOG_INF("Unregistered callback for GPIO pin %d", pin); - return ret; +int ocre_gpio_unregister_callback(int pin) +{ + if (pin >= CONFIG_OCRE_GPIO_MAX_PINS || !gpio_pins[pin].in_use || !gpio_pins[pin].cb || + !port_ready[gpio_pins[pin].port_idx]) { + LOG_ERR("Invalid GPIO pin %d or no callback registered or port not ready", pin); + return -EINVAL; + } + gpio_pin_ocre *gpio = &gpio_pins[pin]; + int ret = gpio_pin_interrupt_configure(gpio_ports[gpio->port_idx], gpio->pin_number, GPIO_INT_DISABLE); + if (ret) { + LOG_ERR("Failed to disable interrupt for GPIO pin %d: %d", pin, ret); + return ret; + } + ret = gpio_remove_callback(gpio_ports[gpio->port_idx], gpio->cb); + if (ret) { + LOG_ERR("Failed to remove callback for GPIO pin %d: %d", pin, ret); + } + k_free(gpio->cb); + gpio->cb = NULL; + LOG_INF("Unregistered callback for GPIO pin %d", pin); + return ret; } -void ocre_gpio_cleanup_container(wasm_module_inst_t module_inst) { - if (!gpio_system_initialized || !module_inst) { - LOG_ERR("GPIO system not initialized or invalid module %p", (void *)module_inst); - return; - } - for (int i = 0; i < CONFIG_OCRE_GPIO_MAX_PINS; i++) { - if (gpio_pins[i].in_use && gpio_pins[i].owner == module_inst) { - if (gpio_pins[i].direction == 0) { - ocre_gpio_unregister_callback(i); - } - gpio_pins[i].in_use = 0; - gpio_pins[i].owner = NULL; - ocre_decrement_resource_count(module_inst, OCRE_RESOURCE_TYPE_GPIO); - LOG_DBG("Cleaned up GPIO pin %d", i); - } - } - LOG_DBG("Cleaned up GPIO resources for module %p", (void *)module_inst); +void ocre_gpio_cleanup_container(wasm_module_inst_t module_inst) +{ + if (!gpio_system_initialized || !module_inst) { + LOG_DBG("GPIO system not initialized or invalid module %p", (void *)module_inst); + return; + } + for (int i = 0; i < CONFIG_OCRE_GPIO_MAX_PINS; i++) { + if (gpio_pins[i].in_use && gpio_pins[i].owner == module_inst) { + if (gpio_pins[i].direction == 0) { + ocre_gpio_unregister_callback(i); + } + gpio_pins[i].in_use = 0; + gpio_pins[i].owner = NULL; + ocre_decrement_resource_count(module_inst, OCRE_RESOURCE_TYPE_GPIO); + LOG_DBG("Cleaned up GPIO pin %d", i); + } + } + LOG_DBG("Cleaned up GPIO resources for module %p", (void *)module_inst); } -void ocre_gpio_set_dispatcher(wasm_exec_env_t exec_env) { - wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); - if (module_inst) { - // Dispatcher set in wasm container application - LOG_INF("Set dispatcher for module %p", (void *)module_inst); - } +void ocre_gpio_set_dispatcher(wasm_exec_env_t exec_env) +{ + wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); + if (module_inst) { + // Dispatcher set in wasm container application + LOG_INF("Set dispatcher for module %p", (void *)module_inst); + } } -int ocre_gpio_wasm_init(wasm_exec_env_t exec_env) { - return ocre_gpio_init(); +int ocre_gpio_wasm_init(wasm_exec_env_t exec_env) +{ + return ocre_gpio_init(); } -int ocre_gpio_wasm_configure(wasm_exec_env_t exec_env, int port, int pin, int direction) { - wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); - if (!module_inst) { - LOG_ERR("No module instance for GPIO configuration"); - return -EINVAL; - } - if (port >= CONFIG_OCRE_GPIO_MAX_PORTS || pin >= CONFIG_OCRE_GPIO_PINS_PER_PORT || !port_ready[port]) { - LOG_ERR("Invalid port=%d, pin=%d, or port not ready", port, pin); - return -EINVAL; - } - int global_pin = port * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; - LOG_INF("Configuring GPIO: port=%d, pin=%d, global_pin=%d, direction=%d", port, pin, global_pin, direction); - if (global_pin >= CONFIG_OCRE_GPIO_MAX_PINS) { - LOG_ERR("Global pin %d exceeds max %d", global_pin, CONFIG_OCRE_GPIO_MAX_PINS); - return -EINVAL; - } - ocre_gpio_config_t config = {.pin = pin, .port_idx = port, .direction = direction}; - return ocre_gpio_configure(&config); +int ocre_gpio_wasm_configure(wasm_exec_env_t exec_env, int port, int pin, int direction) +{ + wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); + if (!module_inst) { + LOG_ERR("No module instance for GPIO configuration"); + return -EINVAL; + } + if (port >= CONFIG_OCRE_GPIO_MAX_PORTS || pin >= CONFIG_OCRE_GPIO_PINS_PER_PORT || !port_ready[port]) { + LOG_ERR("Invalid port=%d, pin=%d, or port not ready", port, pin); + return -EINVAL; + } + int global_pin = port * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; + LOG_INF("Configuring GPIO: port=%d, pin=%d, global_pin=%d, direction=%d", port, pin, global_pin, direction); + if (global_pin >= CONFIG_OCRE_GPIO_MAX_PINS) { + LOG_ERR("Global pin %d exceeds max %d", global_pin, CONFIG_OCRE_GPIO_MAX_PINS); + return -EINVAL; + } + ocre_gpio_config_t config = {.pin = pin, .port_idx = port, .direction = direction}; + return ocre_gpio_configure(&config); } -int ocre_gpio_wasm_set(wasm_exec_env_t exec_env, int port, int pin, int state) { - int global_pin = port * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; - LOG_INF("Setting GPIO: port=%d, pin=%d, global_pin=%d, state=%d", port, pin, global_pin, state); - if (!port_ready[port]) { - LOG_ERR("Port %d not ready", port); - return -EINVAL; - } - return ocre_gpio_pin_set(global_pin, state ? OCRE_GPIO_PIN_SET : OCRE_GPIO_PIN_RESET); +int ocre_gpio_wasm_set(wasm_exec_env_t exec_env, int port, int pin, int state) +{ + int global_pin = port * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; + LOG_INF("Setting GPIO: port=%d, pin=%d, global_pin=%d, state=%d", port, pin, global_pin, state); + if (!port_ready[port]) { + LOG_ERR("Port %d not ready", port); + return -EINVAL; + } + return ocre_gpio_pin_set(global_pin, state ? OCRE_GPIO_PIN_SET : OCRE_GPIO_PIN_RESET); } -int ocre_gpio_wasm_get(wasm_exec_env_t exec_env, int port, int pin) { - int global_pin = port * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; - LOG_INF("Getting GPIO: port=%d, pin=%d, global_pin=%d", port, pin, global_pin); - if (!port_ready[port]) { - LOG_ERR("Port %d not ready", port); - return -EINVAL; - } - return ocre_gpio_pin_get(global_pin); +int ocre_gpio_wasm_get(wasm_exec_env_t exec_env, int port, int pin) +{ + int global_pin = port * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; + LOG_INF("Getting GPIO: port=%d, pin=%d, global_pin=%d", port, pin, global_pin); + if (!port_ready[port]) { + LOG_ERR("Port %d not ready", port); + return -EINVAL; + } + return ocre_gpio_pin_get(global_pin); } -int ocre_gpio_wasm_toggle(wasm_exec_env_t exec_env, int port, int pin) { - int global_pin = port * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; - LOG_INF("Toggling GPIO: port=%d, pin=%d, global_pin=%d", port, pin, global_pin); - if (!port_ready[port]) { - LOG_ERR("Port %d not ready", port); - return -EINVAL; - } - return ocre_gpio_pin_toggle(global_pin); +int ocre_gpio_wasm_toggle(wasm_exec_env_t exec_env, int port, int pin) +{ + int global_pin = port * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; + LOG_INF("Toggling GPIO: port=%d, pin=%d, global_pin=%d", port, pin, global_pin); + if (!port_ready[port]) { + LOG_ERR("Port %d not ready", port); + return -EINVAL; + } + return ocre_gpio_pin_toggle(global_pin); } -int ocre_gpio_wasm_register_callback(wasm_exec_env_t exec_env, int port, int pin) { - int global_pin = port * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; - LOG_INF("Registering callback: port=%d, pin=%d, global_pin=%d", port, pin, global_pin); - if (global_pin >= CONFIG_OCRE_GPIO_MAX_PINS || !port_ready[port]) { - LOG_ERR("Global pin %d exceeds max %d or port %d not ready", global_pin, CONFIG_OCRE_GPIO_MAX_PINS, port); - return -EINVAL; - } - return ocre_gpio_register_callback(global_pin); +int ocre_gpio_wasm_register_callback(wasm_exec_env_t exec_env, int port, int pin) +{ + int global_pin = port * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; + LOG_INF("Registering callback: port=%d, pin=%d, global_pin=%d", port, pin, global_pin); + if (global_pin >= CONFIG_OCRE_GPIO_MAX_PINS || !port_ready[port]) { + LOG_ERR("Global pin %d exceeds max %d or port %d not ready", global_pin, CONFIG_OCRE_GPIO_MAX_PINS, + port); + return -EINVAL; + } + return ocre_gpio_register_callback(global_pin); } -int ocre_gpio_wasm_unregister_callback(wasm_exec_env_t exec_env, int port, int pin) { - int global_pin = port * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; - LOG_INF("Unregistering callback: port=%d, pin=%d, global_pin=%d", port, pin, global_pin); - if (!port_ready[port]) { - LOG_ERR("Port %d not ready", port); - return -EINVAL; - } - return ocre_gpio_unregister_callback(global_pin); +int ocre_gpio_wasm_unregister_callback(wasm_exec_env_t exec_env, int port, int pin) +{ + int global_pin = port * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; + LOG_INF("Unregistering callback: port=%d, pin=%d, global_pin=%d", port, pin, global_pin); + if (!port_ready[port]) { + LOG_ERR("Port %d not ready", port); + return -EINVAL; + } + return ocre_gpio_unregister_callback(global_pin); } -static void gpio_callback_handler(const struct device *port, struct gpio_callback *cb, gpio_port_pins_t pins) { - if (!port || !cb) { - LOG_ERR("Null port or callback in GPIO handler"); - return; - } - for (int i = 0; i < CONFIG_OCRE_GPIO_MAX_PINS; i++) { - if (gpio_pins[i].in_use && gpio_pins[i].cb == cb && (pins & BIT(gpio_pins[i].pin_number))) { - int state = gpio_pin_get(port, gpio_pins[i].pin_number); - if (state >= 0) { - - ocre_event_t event; - event.type = OCRE_RESOURCE_TYPE_GPIO; - event.data.gpio_event.pin_id = gpio_pins[i].pin_number; - event.data.gpio_event.port = gpio_pins[i].port_idx; - event.data.gpio_event.state = (uint32_t)state; - event.owner = gpio_pins[i].owner; - core_spinlock_key_t key = core_spinlock_lock(&ocre_event_queue_lock); - if (core_eventq_put(&ocre_event_queue, &event) != 0) { - LOG_ERR("Failed to queue GPIO event for pin %d", i); - } else { - LOG_INF("Queued GPIO event for pin %d (port=%d, pin=%d), state=%d", i, gpio_pins[i].port_idx, - gpio_pins[i].pin_number, state); - } - core_spinlock_unlock(&ocre_event_queue_lock, key); - } - } - } +static void gpio_callback_handler(const struct device *port, struct gpio_callback *cb, gpio_port_pins_t pins) +{ + if (!port || !cb) { + LOG_ERR("Null port or callback in GPIO handler"); + return; + } + for (int i = 0; i < CONFIG_OCRE_GPIO_MAX_PINS; i++) { + if (gpio_pins[i].in_use && gpio_pins[i].cb == cb && (pins & BIT(gpio_pins[i].pin_number))) { + int state = gpio_pin_get(port, gpio_pins[i].pin_number); + if (state >= 0) { + + ocre_event_t event; + event.type = OCRE_RESOURCE_TYPE_GPIO; + event.data.gpio_event.pin_id = gpio_pins[i].pin_number; + event.data.gpio_event.port = gpio_pins[i].port_idx; + event.data.gpio_event.state = (uint32_t)state; + event.owner = gpio_pins[i].owner; + core_spinlock_key_t key = core_spinlock_lock(&ocre_event_queue_lock); + if (core_eventq_put(&ocre_event_queue, &event) != 0) { + LOG_ERR("Failed to queue GPIO event for pin %d", i); + } else { + LOG_INF("Queued GPIO event for pin %d (port=%d, pin=%d), state=%d", i, + gpio_pins[i].port_idx, gpio_pins[i].pin_number, state); + } + core_spinlock_unlock(&ocre_event_queue_lock, key); + } + } + } } //======================================================================================================================================================================================================================================================================================================== // By Name //======================================================================================================================================================================================================================================================================================================== -static int find_port_index(const struct device *port) { - if (!port) { - LOG_ERR("Null port provided to find_port_index"); - return -EINVAL; - } - for (int i = 0; i < CONFIG_OCRE_GPIO_MAX_PORTS; i++) { - if (port_ready[i] && gpio_ports[i] == port) { - LOG_DBG("Found port at index %d: %p", i, port); - return i; - } - } - LOG_ERR("Port %p not found in initialized ports", port); - return -1; +static int find_port_index(const struct device *port) +{ + if (!port) { + LOG_ERR("Null port provided to find_port_index"); + return -EINVAL; + } + for (int i = 0; i < CONFIG_OCRE_GPIO_MAX_PORTS; i++) { + if (port_ready[i] && gpio_ports[i] == port) { + LOG_DBG("Found port at index %d: %p", i, port); + return i; + } + } + LOG_ERR("Port %p not found in initialized ports", port); + return -1; } -static int resolve_gpio_alias(const char *name, int *port_idx, gpio_pin_t *pin) { - if (!name || !port_idx || !pin) { - LOG_ERR("Invalid parameters: name=%p, port_idx=%p, pin=%p", name, port_idx, pin); - return -EINVAL; - } - - // Check if GPIO system is initialized - if (!gpio_system_initialized) { - LOG_ERR("GPIO system not initialized when resolving alias '%s'", name); - return -ENODEV; - } - - // First check if we already have this alias cached - for (int i = 0; i < gpio_alias_count; i++) { - if (strcmp(gpio_aliases[i].name, name) == 0) { - *port_idx = gpio_aliases[i].port_idx; - *pin = gpio_aliases[i].pin; - LOG_INF("Found cached GPIO alias '%s': port %d, pin %d", name, *port_idx, *pin); - return 0; - } - } - - // Try to resolve the alias using devicetree - const struct gpio_dt_spec *spec = NULL; - static struct gpio_dt_spec gpio_spec; - - // Check common aliases - only compile if they exist - if (strcmp(name, "led0") == 0) { +static int resolve_gpio_alias(const char *name, int *port_idx, gpio_pin_t *pin) +{ + if (!name || !port_idx || !pin) { + LOG_ERR("Invalid parameters: name=%p, port_idx=%p, pin=%p", name, port_idx, pin); + return -EINVAL; + } + + // Check if GPIO system is initialized + if (!gpio_system_initialized) { + LOG_ERR("GPIO system not initialized when resolving alias '%s'", name); + return -ENODEV; + } + + // First check if we already have this alias cached + for (int i = 0; i < gpio_alias_count; i++) { + if (strcmp(gpio_aliases[i].name, name) == 0) { + *port_idx = gpio_aliases[i].port_idx; + *pin = gpio_aliases[i].pin; + LOG_INF("Found cached GPIO alias '%s': port %d, pin %d", name, *port_idx, *pin); + return 0; + } + } + + // Try to resolve the alias using devicetree + const struct gpio_dt_spec *spec = NULL; + static struct gpio_dt_spec gpio_spec; + + // Check common aliases - only compile if they exist + if (strcmp(name, "led0") == 0) { #if DT_NODE_EXISTS(DT_ALIAS(led0)) - gpio_spec = (struct gpio_dt_spec)GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios); - spec = &gpio_spec; - LOG_DBG("Resolved DT_ALIAS(led0) to port %p, pin %d", spec ? spec->port : NULL, spec ? spec->pin : 0); + gpio_spec = (struct gpio_dt_spec)GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios); + spec = &gpio_spec; + LOG_DBG("Resolved DT_ALIAS(led0) to port %p, pin %d", spec ? spec->port : NULL, spec ? spec->pin : 0); #else - LOG_ERR("DT_ALIAS(led0) not defined in device tree"); - return -ENODEV; + LOG_ERR("DT_ALIAS(led0) not defined in device tree"); + return -ENODEV; #endif - } else if (strcmp(name, "led1") == 0) { + } else if (strcmp(name, "led1") == 0) { #if DT_NODE_EXISTS(DT_ALIAS(led1)) - gpio_spec = (struct gpio_dt_spec)GPIO_DT_SPEC_GET(DT_ALIAS(led1), gpios); - spec = &gpio_spec; - LOG_DBG("Resolved DT_ALIAS(led1) to port %p, pin %d", spec ? spec->port : NULL, spec ? spec->pin : 0); + gpio_spec = (struct gpio_dt_spec)GPIO_DT_SPEC_GET(DT_ALIAS(led1), gpios); + spec = &gpio_spec; + LOG_DBG("Resolved DT_ALIAS(led1) to port %p, pin %d", spec ? spec->port : NULL, spec ? spec->pin : 0); #else - LOG_ERR("DT_ALIAS(led1) not defined in device tree"); - return -ENODEV; + LOG_ERR("DT_ALIAS(led1) not defined in device tree"); + return -ENODEV; #endif - } else if (strcmp(name, "led2") == 0) { + } else if (strcmp(name, "led2") == 0) { #if DT_NODE_EXISTS(DT_ALIAS(led2)) - gpio_spec = (struct gpio_dt_spec)GPIO_DT_SPEC_GET(DT_ALIAS(led2), gpios); - spec = &gpio_spec; - LOG_DBG("Resolved DT_ALIAS(led2) to port %p, pin %d", spec ? spec->port : NULL, spec ? spec->pin : 0); + gpio_spec = (struct gpio_dt_spec)GPIO_DT_SPEC_GET(DT_ALIAS(led2), gpios); + spec = &gpio_spec; + LOG_DBG("Resolved DT_ALIAS(led2) to port %p, pin %d", spec ? spec->port : NULL, spec ? spec->pin : 0); #else - LOG_ERR("DT_ALIAS(led2) not defined in device tree"); - return -ENODEV; + LOG_ERR("DT_ALIAS(led2) not defined in device tree"); + return -ENODEV; #endif - } else if (strcmp(name, "sw0") == 0) { + } else if (strcmp(name, "sw0") == 0) { #if DT_NODE_EXISTS(DT_ALIAS(sw0)) - gpio_spec = (struct gpio_dt_spec)GPIO_DT_SPEC_GET(DT_ALIAS(sw0), gpios); - spec = &gpio_spec; - LOG_DBG("Resolved DT_ALIAS(sw0) to port %p, pin %d", spec ? spec->port : NULL, spec ? spec->pin : 0); + gpio_spec = (struct gpio_dt_spec)GPIO_DT_SPEC_GET(DT_ALIAS(sw0), gpios); + spec = &gpio_spec; + LOG_DBG("Resolved DT_ALIAS(sw0) to port %p, pin %d", spec ? spec->port : NULL, spec ? spec->pin : 0); #else - LOG_ERR("DT_ALIAS(sw0) not defined in device tree"); - return -ENODEV; + LOG_ERR("DT_ALIAS(sw0) not defined in device tree"); + return -ENODEV; #endif - } else if (strcmp(name, "sw1") == 0) { + } else if (strcmp(name, "sw1") == 0) { #if DT_NODE_EXISTS(DT_ALIAS(sw1)) - gpio_spec = (struct gpio_dt_spec)GPIO_DT_SPEC_GET(DT_ALIAS(sw1), gpios); - spec = &gpio_spec; - LOG_DBG("Resolved DT_ALIAS(sw1) to port %p, pin %d", spec ? spec->port : NULL, spec ? spec->pin : 0); + gpio_spec = (struct gpio_dt_spec)GPIO_DT_SPEC_GET(DT_ALIAS(sw1), gpios); + spec = &gpio_spec; + LOG_DBG("Resolved DT_ALIAS(sw1) to port %p, pin %d", spec ? spec->port : NULL, spec ? spec->pin : 0); #else - LOG_ERR("DT_ALIAS(sw1) not defined in device tree"); - return -ENODEV; + LOG_ERR("DT_ALIAS(sw1) not defined in device tree"); + return -ENODEV; #endif - } else { - LOG_ERR("Unknown GPIO alias '%s'", name); - return -EINVAL; - } - - if (!spec || !spec->port) { - LOG_ERR("GPIO alias '%s' not found in device tree or invalid spec", name); - return -ENODEV; - } - - // Verify device readiness - if (!device_is_ready(spec->port)) { - LOG_ERR("Device for GPIO alias '%s' (port %p) not ready", name, spec->port); - return -ENODEV; - } - - // Find the port index - int found_port_idx = find_port_index(spec->port); - if (found_port_idx < 0) { - LOG_ERR("Port for alias '%s' (port %p) not found in initialized ports", name, spec->port); - // Debug: print all available ports - LOG_ERR("Available ports:"); - bool any_ports = false; - for (int i = 0; i < CONFIG_OCRE_GPIO_MAX_PORTS; i++) { - if (port_ready[i] && gpio_ports[i]) { - LOG_ERR(" Port %d: %p", i, gpio_ports[i]); - any_ports = true; - } - } - if (!any_ports) { - LOG_ERR(" No ports initialized"); - } - LOG_ERR("Looking for port: %p", spec->port); - return -ENODEV; - } - - *port_idx = found_port_idx; - *pin = spec->pin; - - // Cache the resolved alias - if (gpio_alias_count < CONFIG_OCRE_GPIO_MAX_PINS) { - gpio_aliases[gpio_alias_count].name = name; - gpio_aliases[gpio_alias_count].port = spec->port; - gpio_aliases[gpio_alias_count].pin = spec->pin; - gpio_aliases[gpio_alias_count].port_idx = found_port_idx; - gpio_alias_count++; - LOG_INF("Cached GPIO alias '%s': port %d, pin %d", name, found_port_idx, spec->pin); - } else { - LOG_WRN("Cannot cache alias '%s': alias table full", name); - } - - LOG_INF("Resolved GPIO alias '%s' to port %d, pin %d", name, *port_idx, *pin); - return 0; + } else { + LOG_ERR("Unknown GPIO alias '%s'", name); + return -EINVAL; + } + + if (!spec || !spec->port) { + LOG_ERR("GPIO alias '%s' not found in device tree or invalid spec", name); + return -ENODEV; + } + + // Verify device readiness + if (!device_is_ready(spec->port)) { + LOG_ERR("Device for GPIO alias '%s' (port %p) not ready", name, spec->port); + return -ENODEV; + } + + // Find the port index + int found_port_idx = find_port_index(spec->port); + if (found_port_idx < 0) { + LOG_ERR("Port for alias '%s' (port %p) not found in initialized ports", name, spec->port); + // Debug: print all available ports + LOG_ERR("Available ports:"); + bool any_ports = false; + for (int i = 0; i < CONFIG_OCRE_GPIO_MAX_PORTS; i++) { + if (port_ready[i] && gpio_ports[i]) { + LOG_ERR(" Port %d: %p", i, gpio_ports[i]); + any_ports = true; + } + } + if (!any_ports) { + LOG_ERR(" No ports initialized"); + } + LOG_ERR("Looking for port: %p", spec->port); + return -ENODEV; + } + + *port_idx = found_port_idx; + *pin = spec->pin; + + // Cache the resolved alias + if (gpio_alias_count < CONFIG_OCRE_GPIO_MAX_PINS) { + gpio_aliases[gpio_alias_count].name = name; + gpio_aliases[gpio_alias_count].port = spec->port; + gpio_aliases[gpio_alias_count].pin = spec->pin; + gpio_aliases[gpio_alias_count].port_idx = found_port_idx; + gpio_alias_count++; + LOG_INF("Cached GPIO alias '%s': port %d, pin %d", name, found_port_idx, spec->pin); + } else { + LOG_WRN("Cannot cache alias '%s': alias table full", name); + } + + LOG_INF("Resolved GPIO alias '%s' to port %d, pin %d", name, *port_idx, *pin); + return 0; } -int ocre_gpio_configure_by_name(const char *name, ocre_gpio_direction_t direction) { - if (!name) { - LOG_ERR("Invalid name parameter"); - return -EINVAL; - } - - int port_idx; - gpio_pin_t pin; - int ret = resolve_gpio_alias(name, &port_idx, &pin); - if (ret != 0) { - return ret; - } - - ocre_gpio_config_t config = { - .pin = pin, - .port_idx = port_idx, - .direction = direction - }; - - return ocre_gpio_configure(&config); -} +int ocre_gpio_configure_by_name(const char *name, ocre_gpio_direction_t direction) +{ + if (!name) { + LOG_ERR("Invalid name parameter"); + return -EINVAL; + } -int ocre_gpio_set_by_name(const char *name, ocre_gpio_pin_state_t state) { - if (!name) { - LOG_ERR("Invalid name parameter"); - return -EINVAL; - } - - int port_idx; - gpio_pin_t pin; - int ret = resolve_gpio_alias(name, &port_idx, &pin); - if (ret != 0) { - return ret; - } - - int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; - return ocre_gpio_pin_set(global_pin, state); -} + int port_idx; + gpio_pin_t pin; + int ret = resolve_gpio_alias(name, &port_idx, &pin); + if (ret != 0) { + return ret; + } -int ocre_gpio_toggle_by_name(const char *name) { - if (!name) { - LOG_ERR("Invalid name parameter"); - return -EINVAL; - } - - int port_idx; - gpio_pin_t pin; - int ret = resolve_gpio_alias(name, &port_idx, &pin); - if (ret != 0) { - return ret; - } - - int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; - return ocre_gpio_pin_toggle(global_pin); + ocre_gpio_config_t config = {.pin = pin, .port_idx = port_idx, .direction = direction}; + + return ocre_gpio_configure(&config); } -ocre_gpio_pin_state_t ocre_gpio_get_by_name(const char *name) { - if (!name) { - LOG_ERR("Invalid name parameter"); - return -EINVAL; - } - - int port_idx; - gpio_pin_t pin; - int ret = resolve_gpio_alias(name, &port_idx, &pin); - if (ret != 0) { - return ret; - } - - int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; - return ocre_gpio_pin_get(global_pin); +int ocre_gpio_set_by_name(const char *name, ocre_gpio_pin_state_t state) +{ + if (!name) { + LOG_ERR("Invalid name parameter"); + return -EINVAL; + } + + int port_idx; + gpio_pin_t pin; + int ret = resolve_gpio_alias(name, &port_idx, &pin); + if (ret != 0) { + return ret; + } + + int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; + return ocre_gpio_pin_set(global_pin, state); } -int ocre_gpio_wasm_configure_by_name(wasm_exec_env_t exec_env, const char *name, int direction) { - if (!name) { - LOG_ERR("Invalid name parameter"); - return -EINVAL; - } +int ocre_gpio_toggle_by_name(const char *name) +{ + if (!name) { + LOG_ERR("Invalid name parameter"); + return -EINVAL; + } + + int port_idx; + gpio_pin_t pin; + int ret = resolve_gpio_alias(name, &port_idx, &pin); + if (ret != 0) { + return ret; + } + + int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; + return ocre_gpio_pin_toggle(global_pin); +} - wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); - if (!module_inst) { - LOG_ERR("No module instance for GPIO configuration"); - return -EINVAL; - } +ocre_gpio_pin_state_t ocre_gpio_get_by_name(const char *name) +{ + if (!name) { + LOG_ERR("Invalid name parameter"); + return -EINVAL; + } + + int port_idx; + gpio_pin_t pin; + int ret = resolve_gpio_alias(name, &port_idx, &pin); + if (ret != 0) { + return ret; + } + + int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; + return ocre_gpio_pin_get(global_pin); +} - LOG_INF("Configuring GPIO by name: %s, direction=%d", name, direction); - return ocre_gpio_configure_by_name(name, direction); +int ocre_gpio_wasm_configure_by_name(wasm_exec_env_t exec_env, const char *name, int direction) +{ + if (!name) { + LOG_ERR("Invalid name parameter"); + return -EINVAL; + } + + wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); + if (!module_inst) { + LOG_ERR("No module instance for GPIO configuration"); + return -EINVAL; + } + + LOG_INF("Configuring GPIO by name: %s, direction=%d", name, direction); + return ocre_gpio_configure_by_name(name, direction); } -int ocre_gpio_wasm_set_by_name(wasm_exec_env_t exec_env, const char *name, int state) { - if (!name) { - LOG_ERR("Invalid name parameter"); - return -EINVAL; - } +int ocre_gpio_wasm_set_by_name(wasm_exec_env_t exec_env, const char *name, int state) +{ + if (!name) { + LOG_ERR("Invalid name parameter"); + return -EINVAL; + } - LOG_INF("Setting GPIO by name: %s, state=%d", name, state); - return ocre_gpio_set_by_name(name, state ? OCRE_GPIO_PIN_SET : OCRE_GPIO_PIN_RESET); + LOG_INF("Setting GPIO by name: %s, state=%d", name, state); + return ocre_gpio_set_by_name(name, state ? OCRE_GPIO_PIN_SET : OCRE_GPIO_PIN_RESET); } -int ocre_gpio_wasm_get_by_name(wasm_exec_env_t exec_env, const char *name) { - if (!name) { - LOG_ERR("Invalid name parameter"); - return -EINVAL; - } +int ocre_gpio_wasm_get_by_name(wasm_exec_env_t exec_env, const char *name) +{ + if (!name) { + LOG_ERR("Invalid name parameter"); + return -EINVAL; + } - LOG_INF("Getting GPIO by name: %s", name); - return ocre_gpio_get_by_name(name); + LOG_INF("Getting GPIO by name: %s", name); + return ocre_gpio_get_by_name(name); } -int ocre_gpio_wasm_toggle_by_name(wasm_exec_env_t exec_env, const char *name) { - if (!name) { - LOG_ERR("Invalid name parameter"); - return -EINVAL; - } +int ocre_gpio_wasm_toggle_by_name(wasm_exec_env_t exec_env, const char *name) +{ + if (!name) { + LOG_ERR("Invalid name parameter"); + return -EINVAL; + } - LOG_INF("Toggling GPIO by name: %s", name); - return ocre_gpio_toggle_by_name(name); + LOG_INF("Toggling GPIO by name: %s", name); + return ocre_gpio_toggle_by_name(name); } -int ocre_gpio_wasm_register_callback_by_name(wasm_exec_env_t exec_env, const char *name) { - if (!name) { - LOG_ERR("Invalid name parameter"); - return -EINVAL; - } - - int port_idx; - gpio_pin_t pin; - int ret = resolve_gpio_alias(name, &port_idx, &pin); - if (ret != 0) { - return ret; - } - - int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; - LOG_INF("Registering callback by name: %s, global_pin=%d", name, global_pin); - - if (global_pin >= CONFIG_OCRE_GPIO_MAX_PINS) { - LOG_ERR("Global pin %d exceeds max %d", global_pin, CONFIG_OCRE_GPIO_MAX_PINS); - return -EINVAL; - } - - return ocre_gpio_register_callback(global_pin); +int ocre_gpio_wasm_register_callback_by_name(wasm_exec_env_t exec_env, const char *name) +{ + if (!name) { + LOG_ERR("Invalid name parameter"); + return -EINVAL; + } + + int port_idx; + gpio_pin_t pin; + int ret = resolve_gpio_alias(name, &port_idx, &pin); + if (ret != 0) { + return ret; + } + + int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; + LOG_INF("Registering callback by name: %s, global_pin=%d", name, global_pin); + + if (global_pin >= CONFIG_OCRE_GPIO_MAX_PINS) { + LOG_ERR("Global pin %d exceeds max %d", global_pin, CONFIG_OCRE_GPIO_MAX_PINS); + return -EINVAL; + } + + return ocre_gpio_register_callback(global_pin); } -int ocre_gpio_wasm_unregister_callback_by_name(wasm_exec_env_t exec_env, const char *name) { - if (!name) { - LOG_ERR("Invalid name parameter"); - return -EINVAL; - } - - int port_idx; - gpio_pin_t pin; - int ret = resolve_gpio_alias(name, &port_idx, &pin); - if (ret != 0) { - return ret; - } - - int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; - LOG_INF("Unregistering callback by name: %s, global_pin=%d", name, global_pin); - - return ocre_gpio_unregister_callback(global_pin); +int ocre_gpio_wasm_unregister_callback_by_name(wasm_exec_env_t exec_env, const char *name) +{ + if (!name) { + LOG_ERR("Invalid name parameter"); + return -EINVAL; + } + + int port_idx; + gpio_pin_t pin; + int ret = resolve_gpio_alias(name, &port_idx, &pin); + if (ret != 0) { + return ret; + } + + int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; + LOG_INF("Unregistering callback by name: %s, global_pin=%d", name, global_pin); + + return ocre_gpio_unregister_callback(global_pin); } diff --git a/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.h b/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.h index 80e48bc0..74258537 100644 --- a/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.h +++ b/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.h @@ -29,25 +29,25 @@ * GPIO pin state */ typedef enum { - OCRE_GPIO_PIN_RESET = 0, - OCRE_GPIO_PIN_SET = 1 + OCRE_GPIO_PIN_RESET = 0, + OCRE_GPIO_PIN_SET = 1 } ocre_gpio_pin_state_t; /** * GPIO pin direction */ typedef enum { - OCRE_GPIO_DIR_INPUT = 0, - OCRE_GPIO_DIR_OUTPUT = 1 + OCRE_GPIO_DIR_INPUT = 0, + OCRE_GPIO_DIR_OUTPUT = 1 } ocre_gpio_direction_t; /** * GPIO configuration structure */ typedef struct { - int pin; /**< GPIO pin number (logical) */ - int port_idx; - ocre_gpio_direction_t direction; /**< Pin direction */ + int pin; /**< GPIO pin number (logical) */ + int port_idx; + ocre_gpio_direction_t direction; /**< Pin direction */ } ocre_gpio_config_t; /** @@ -128,7 +128,7 @@ void ocre_gpio_set_dispatcher(wasm_exec_env_t exec_env); /** * @brief Configure a GPIO pin by alias name - * + * * @param name GPIO alias name (e.g., "led0", "sw0") * @param direction GPIO direction (OCRE_GPIO_DIR_INPUT or OCRE_GPIO_DIR_OUTPUT) * @return int 0 on success, negative error code on failure @@ -137,7 +137,7 @@ int ocre_gpio_configure_by_name(const char *name, ocre_gpio_direction_t directio /** * @brief Set a GPIO pin state by alias name - * + * * @param name GPIO alias name (e.g., "led0", "sw0") * @param state Pin state (OCRE_GPIO_PIN_SET or OCRE_GPIO_PIN_RESET) * @return int 0 on success, negative error code on failure @@ -146,7 +146,7 @@ int ocre_gpio_set_by_name(const char *name, ocre_gpio_pin_state_t state); /** * @brief Toggle a GPIO pin by alias name - * + * * @param name GPIO alias name (e.g., "led0", "sw0") * @return int 0 on success, negative error code on failure */ @@ -154,7 +154,7 @@ int ocre_gpio_toggle_by_name(const char *name); /** * @brief Get a GPIO pin state by alias name - * + * * @param name GPIO alias name (e.g., "led0", "sw0") * @return ocre_gpio_pin_state_t Pin state or negative error code on failure */ diff --git a/src/runtime/wamr/ocre_api/ocre_sensors/ocre_sensors.c b/src/runtime/wamr/ocre_api/ocre_sensors/ocre_sensors.c index f304ed86..285ae090 100644 --- a/src/runtime/wamr/ocre_api/ocre_sensors/ocre_sensors.c +++ b/src/runtime/wamr/ocre_api/ocre_sensors/ocre_sensors.c @@ -13,14 +13,14 @@ LOG_MODULE_REGISTER(ocre_sensors, CONFIG_OCRE_LOG_LEVEL); #include "ocre_sensors.h" -#define DEVICE_NODE DT_PATH(devices) +#define DEVICE_NODE DT_PATH(devices) #define HAS_DEVICE_NODES DT_NODE_EXISTS(DEVICE_NODE) && DT_PROP_LEN(DEVICE_NODE, device_list) > 1 /* Define sensor discovery names from device tree if available */ #if (CONFIG_OCRE_SENSORS) && (HAS_DEVICE_NODES) #define EXTRACT_LABELS(node_id, prop, idx) DT_PROP_BY_PHANDLE_IDX_OR(node_id, prop, idx, label, "undefined") static const char *sensor_discovery_names[] = { - DT_FOREACH_PROP_ELEM_SEP(DEVICE_NODE, device_list, EXTRACT_LABELS, (, ))}; + DT_FOREACH_PROP_ELEM_SEP(DEVICE_NODE, device_list, EXTRACT_LABELS, (, ))}; static int sensor_names_count = sizeof(sensor_discovery_names) / sizeof(sensor_discovery_names[0]); #else static const char *sensor_discovery_names[] = {}; @@ -28,266 +28,282 @@ static int sensor_names_count = 0; #endif typedef struct { - const struct device *device; - ocre_sensor_t info; - bool in_use; + const struct device *device; + ocre_sensor_t info; + bool in_use; } ocre_sensor_internal_t; static ocre_sensor_internal_t sensors[CONFIG_MAX_SENSORS] = {0}; static int sensor_count = 0; -static int set_opened_channels(const struct device *dev, enum sensor_channel *channels) { - if (!channels) { - LOG_ERR("Channels array is NULL"); - return -EINVAL; - } - - if (!device_is_ready(dev)) { - LOG_ERR("Device is not ready"); - return -ENODEV; - } - - if (sensor_sample_fetch(dev) < 0) { - LOG_WRN("Failed to fetch sensor data - sensor might not be initialized"); - } - - int count = 0; - struct sensor_value value = {}; - - for (int channel = 0; channel < SENSOR_CHAN_ALL && count < CONFIG_MAX_CHANNELS_PER_SENSOR; channel++) { - if (channel != SENSOR_CHAN_ACCEL_XYZ && channel != SENSOR_CHAN_GYRO_XYZ && channel != SENSOR_CHAN_MAGN_XYZ && - channel != SENSOR_CHAN_POS_DXYZ) { - if (sensor_channel_get(dev, channel, &value) == 0) { - channels[count] = channel; - count++; - } - } - } - return count; +static int set_opened_channels(const struct device *dev, enum sensor_channel *channels) +{ + if (!channels) { + LOG_ERR("Channels array is NULL"); + return -EINVAL; + } + + if (!device_is_ready(dev)) { + LOG_ERR("Device is not ready"); + return -ENODEV; + } + + if (sensor_sample_fetch(dev) < 0) { + LOG_WRN("Failed to fetch sensor data - sensor might not be initialized"); + } + + int count = 0; + struct sensor_value value = {}; + + for (int channel = 0; channel < SENSOR_CHAN_ALL && count < CONFIG_MAX_CHANNELS_PER_SENSOR; channel++) { + if (channel != SENSOR_CHAN_ACCEL_XYZ && channel != SENSOR_CHAN_GYRO_XYZ && + channel != SENSOR_CHAN_MAGN_XYZ && channel != SENSOR_CHAN_POS_DXYZ) { + if (sensor_channel_get(dev, channel, &value) == 0) { + channels[count] = channel; + count++; + } + } + } + return count; } -int ocre_sensors_init(wasm_exec_env_t exec_env) { - memset(sensors, 0, sizeof(sensors)); - sensor_count = 0; - return 0; +int ocre_sensors_init(wasm_exec_env_t exec_env) +{ + memset(sensors, 0, sizeof(sensors)); + sensor_count = 0; + return 0; } -int ocre_sensors_open(wasm_exec_env_t exec_env, ocre_sensor_handle_t handle) { - if (handle < 0 || handle >= sensor_count || !sensors[handle].in_use) { - LOG_ERR("Invalid sensor handle: %d", handle); - return -EINVAL; - } +int ocre_sensors_open(wasm_exec_env_t exec_env, ocre_sensor_handle_t handle) +{ + if (handle < 0 || handle >= sensor_count || !sensors[handle].in_use) { + LOG_ERR("Invalid sensor handle: %d", handle); + return -EINVAL; + } - if (!device_is_ready(sensors[handle].device)) { - LOG_ERR("Device %s is not ready", sensors[handle].info.sensor_name); - return -ENODEV; - } + if (!device_is_ready(sensors[handle].device)) { + LOG_ERR("Device %s is not ready", sensors[handle].info.sensor_name); + return -ENODEV; + } - return 0; + return 0; } -int ocre_sensors_discover(wasm_exec_env_t exec_env) { - memset(sensors, 0, sizeof(sensors)); - sensor_count = 0; - - const struct device *dev = NULL; - size_t device_count = z_device_get_all_static(&dev); - - if (!dev) { - LOG_ERR("Device list is NULL. Possible memory corruption!"); - return -EINVAL; - } - if (device_count == 0) { - LOG_ERR("No static devices found"); - return -ENODEV; - } - - LOG_INF("Total static devices found: %zu", device_count); - - for (size_t i = 0; i < device_count && sensor_count < CONFIG_MAX_SENSORS; i++) { - if (!dev[i].name) { - LOG_ERR("Device %zu has NULL name, skipping!", i); - continue; - } - - LOG_INF("Checking device: %s", dev[i].name); - - bool sensor_found = false; - for (int j = 0; j < sensor_names_count; j++) { - if (strcmp(dev[i].name, sensor_discovery_names[j]) == 0) { - sensor_found = true; - break; - } - } - if (!sensor_found) { - LOG_WRN("Skipping device, not in sensor list: %s", dev[i].name); - continue; - } - - const struct sensor_driver_api *api = (const struct sensor_driver_api *)dev[i].api; - if (!api || !api->channel_get) { - LOG_WRN("Device %s does not support sensor API or channel_get, skipping", dev[i].name); - continue; - } - - if (sensor_count >= CONFIG_MAX_SENSORS) { - LOG_WRN("Max sensor limit reached, skipping device: %s", dev[i].name); - continue; - } - - ocre_sensor_internal_t *sensor = &sensors[sensor_count]; - sensor->device = &dev[i]; - sensor->in_use = true; - sensor->info.handle = sensor_count; - - strncpy(sensor->info.sensor_name, dev[i].name, CONFIG_MAX_SENSOR_NAME_LENGTH - 1); - sensor->info.sensor_name[CONFIG_MAX_SENSOR_NAME_LENGTH - 1] = '\0'; - - sensor->info.num_channels = set_opened_channels(&dev[i], sensor->info.channels); - if (sensor->info.num_channels <= 0) { - LOG_WRN("Device %s does not have opened channels, skipping", dev[i].name); - continue; - } - - LOG_INF("Device has %d channels", sensor->info.num_channels); - sensor_count++; - } - - LOG_INF("Discovered %d sensors", sensor_count); - return sensor_count; +int ocre_sensors_discover(wasm_exec_env_t exec_env) +{ + memset(sensors, 0, sizeof(sensors)); + sensor_count = 0; + + const struct device *dev = NULL; + size_t device_count = z_device_get_all_static(&dev); + + if (!dev) { + LOG_ERR("Device list is NULL. Possible memory corruption!"); + return -EINVAL; + } + if (device_count == 0) { + LOG_ERR("No static devices found"); + return -ENODEV; + } + + LOG_INF("Total static devices found: %zu", device_count); + + for (size_t i = 0; i < device_count && sensor_count < CONFIG_MAX_SENSORS; i++) { + if (!dev[i].name) { + LOG_ERR("Device %zu has NULL name, skipping!", i); + continue; + } + + LOG_INF("Checking device: %s", dev[i].name); + + bool sensor_found = false; + for (int j = 0; j < sensor_names_count; j++) { + if (strcmp(dev[i].name, sensor_discovery_names[j]) == 0) { + sensor_found = true; + break; + } + } + if (!sensor_found) { + LOG_WRN("Skipping device, not in sensor list: %s", dev[i].name); + continue; + } + + const struct sensor_driver_api *api = (const struct sensor_driver_api *)dev[i].api; + if (!api || !api->channel_get) { + LOG_WRN("Device %s does not support sensor API or channel_get, skipping", dev[i].name); + continue; + } + + if (sensor_count >= CONFIG_MAX_SENSORS) { + LOG_WRN("Max sensor limit reached, skipping device: %s", dev[i].name); + continue; + } + + ocre_sensor_internal_t *sensor = &sensors[sensor_count]; + sensor->device = &dev[i]; + sensor->in_use = true; + sensor->info.handle = sensor_count; + + strncpy(sensor->info.sensor_name, dev[i].name, CONFIG_MAX_SENSOR_NAME_LENGTH - 1); + sensor->info.sensor_name[CONFIG_MAX_SENSOR_NAME_LENGTH - 1] = '\0'; + + sensor->info.num_channels = set_opened_channels(&dev[i], sensor->info.channels); + if (sensor->info.num_channels <= 0) { + LOG_WRN("Device %s does not have opened channels, skipping", dev[i].name); + continue; + } + + LOG_INF("Device has %d channels", sensor->info.num_channels); + sensor_count++; + } + + LOG_INF("Discovered %d sensors", sensor_count); + return sensor_count; } -int ocre_sensors_get_handle(wasm_exec_env_t exec_env, int sensor_id) { - if (sensor_id < 0 || sensor_id >= sensor_count || !sensors[sensor_id].in_use) { - return -EINVAL; - } - return sensors[sensor_id].info.handle; +int ocre_sensors_get_handle(wasm_exec_env_t exec_env, int sensor_id) +{ + if (sensor_id < 0 || sensor_id >= sensor_count || !sensors[sensor_id].in_use) { + return -EINVAL; + } + return sensors[sensor_id].info.handle; } -int ocre_sensors_get_name(wasm_exec_env_t exec_env, int sensor_id, char *buffer, int buffer_size) { - if (sensor_id < 0 || sensor_id >= sensor_count || !sensors[sensor_id].in_use || !buffer) { - return -EINVAL; - } +int ocre_sensors_get_name(wasm_exec_env_t exec_env, int sensor_id, char *buffer, int buffer_size) +{ + if (sensor_id < 0 || sensor_id >= sensor_count || !sensors[sensor_id].in_use || !buffer) { + return -EINVAL; + } - int name_len = strlen(sensors[sensor_id].info.sensor_name); - if (name_len >= buffer_size) { - return -ENOSPC; - } + int name_len = strlen(sensors[sensor_id].info.sensor_name); + if (name_len >= buffer_size) { + return -ENOSPC; + } - strncpy(buffer, sensors[sensor_id].info.sensor_name, buffer_size - 1); - buffer[buffer_size - 1] = '\0'; - return name_len; + strncpy(buffer, sensors[sensor_id].info.sensor_name, buffer_size - 1); + buffer[buffer_size - 1] = '\0'; + return name_len; } -int ocre_sensors_get_channel_count(wasm_exec_env_t exec_env, int sensor_id) { - if (sensor_id < 0 || sensor_id >= sensor_count || !sensors[sensor_id].in_use) { - return -EINVAL; - } - return sensors[sensor_id].info.num_channels; +int ocre_sensors_get_channel_count(wasm_exec_env_t exec_env, int sensor_id) +{ + if (sensor_id < 0 || sensor_id >= sensor_count || !sensors[sensor_id].in_use) { + return -EINVAL; + } + return sensors[sensor_id].info.num_channels; } -int ocre_sensors_get_channel_type(wasm_exec_env_t exec_env, int sensor_id, int channel_index) { - if (sensor_id < 0 || sensor_id >= sensor_count || !sensors[sensor_id].in_use || channel_index < 0 || - channel_index >= sensors[sensor_id].info.num_channels) { - return -EINVAL; - } - return sensors[sensor_id].info.channels[channel_index]; +int ocre_sensors_get_channel_type(wasm_exec_env_t exec_env, int sensor_id, int channel_index) +{ + if (sensor_id < 0 || sensor_id >= sensor_count || !sensors[sensor_id].in_use || channel_index < 0 || + channel_index >= sensors[sensor_id].info.num_channels) { + return -EINVAL; + } + return sensors[sensor_id].info.channels[channel_index]; } -double ocre_sensors_read(wasm_exec_env_t exec_env, int sensor_id, int channel_type) { - if (sensor_id < 0 || sensor_id >= sensor_count || !sensors[sensor_id].in_use) { - return -EINVAL; - } +double ocre_sensors_read(wasm_exec_env_t exec_env, int sensor_id, int channel_type) +{ + if (sensor_id < 0 || sensor_id >= sensor_count || !sensors[sensor_id].in_use) { + return -EINVAL; + } - const struct device *dev = sensors[sensor_id].device; - struct sensor_value value = {}; + const struct device *dev = sensors[sensor_id].device; + struct sensor_value value = {}; - if (sensor_sample_fetch(dev) < 0) { - LOG_ERR("Failed to fetch sensor data"); - return -EIO; - } + if (sensor_sample_fetch(dev) < 0) { + LOG_ERR("Failed to fetch sensor data"); + return -EIO; + } - if (sensor_channel_get(dev, channel_type, &value) < 0) { - LOG_ERR("Failed to get scalar channel data"); - return -EIO; - } + if (sensor_channel_get(dev, channel_type, &value) < 0) { + LOG_ERR("Failed to get scalar channel data"); + return -EIO; + } - return sensor_value_to_double(&value); + return sensor_value_to_double(&value); } -static int find_sensor_by_name(const char *name) { - if (!name) { - return -EINVAL; - } +static int find_sensor_by_name(const char *name) +{ + if (!name) { + return -EINVAL; + } - for (int i = 0; i < sensor_count; i++) { - if (sensors[i].in_use && strcmp(sensors[i].info.sensor_name, name) == 0) { - return i; - } - } + for (int i = 0; i < sensor_count; i++) { + if (sensors[i].in_use && strcmp(sensors[i].info.sensor_name, name) == 0) { + return i; + } + } - return -ENOENT; + return -ENOENT; } -int ocre_sensors_open_by_name(wasm_exec_env_t exec_env, const char *sensor_name) { - int sensor_id = find_sensor_by_name(sensor_name); - if (sensor_id < 0) { - LOG_ERR("Sensor not found: %s", sensor_name); - return -ENOENT; - } +int ocre_sensors_open_by_name(wasm_exec_env_t exec_env, const char *sensor_name) +{ + int sensor_id = find_sensor_by_name(sensor_name); + if (sensor_id < 0) { + LOG_ERR("Sensor not found: %s", sensor_name); + return -ENOENT; + } - return ocre_sensors_open(exec_env, sensor_id); + return ocre_sensors_open(exec_env, sensor_id); } -int ocre_sensors_get_handle_by_name(wasm_exec_env_t exec_env, const char *sensor_name) { - int sensor_id = find_sensor_by_name(sensor_name); - if (sensor_id < 0) { - return -ENOENT; - } +int ocre_sensors_get_handle_by_name(wasm_exec_env_t exec_env, const char *sensor_name) +{ + int sensor_id = find_sensor_by_name(sensor_name); + if (sensor_id < 0) { + return -ENOENT; + } - return sensors[sensor_id].info.handle; + return sensors[sensor_id].info.handle; } -int ocre_sensors_get_channel_count_by_name(wasm_exec_env_t exec_env, const char *sensor_name) { - int sensor_id = find_sensor_by_name(sensor_name); - if (sensor_id < 0) { - return -ENOENT; - } +int ocre_sensors_get_channel_count_by_name(wasm_exec_env_t exec_env, const char *sensor_name) +{ + int sensor_id = find_sensor_by_name(sensor_name); + if (sensor_id < 0) { + return -ENOENT; + } - return sensors[sensor_id].info.num_channels; + return sensors[sensor_id].info.num_channels; } -int ocre_sensors_get_channel_type_by_name(wasm_exec_env_t exec_env, const char *sensor_name, int channel_index) { - int sensor_id = find_sensor_by_name(sensor_name); - if (sensor_id < 0) { - return -ENOENT; - } +int ocre_sensors_get_channel_type_by_name(wasm_exec_env_t exec_env, const char *sensor_name, int channel_index) +{ + int sensor_id = find_sensor_by_name(sensor_name); + if (sensor_id < 0) { + return -ENOENT; + } - return ocre_sensors_get_channel_type(exec_env, sensor_id, channel_index); + return ocre_sensors_get_channel_type(exec_env, sensor_id, channel_index); } -double ocre_sensors_read_by_name(wasm_exec_env_t exec_env, const char *sensor_name, int channel_type) { - int sensor_id = find_sensor_by_name(sensor_name); - if (sensor_id < 0) { - LOG_ERR("Sensor not found: %s", sensor_name); - return -ENOENT; - } +double ocre_sensors_read_by_name(wasm_exec_env_t exec_env, const char *sensor_name, int channel_type) +{ + int sensor_id = find_sensor_by_name(sensor_name); + if (sensor_id < 0) { + LOG_ERR("Sensor not found: %s", sensor_name); + return -ENOENT; + } - return ocre_sensors_read(exec_env, sensor_id, channel_type); + return ocre_sensors_read(exec_env, sensor_id, channel_type); } -int ocre_sensors_get_list(wasm_exec_env_t exec_env, char **name_list, int max_names) { - if (!name_list || max_names <= 0) { - return -EINVAL; - } - - int count = 0; - for (int i = 0; i < sensor_count && count < max_names; i++) { - if (sensors[i].in_use) { - name_list[count] = (char *)sensors[i].info.sensor_name; - count++; - } - } - - return count; +int ocre_sensors_get_list(wasm_exec_env_t exec_env, char **name_list, int max_names) +{ + if (!name_list || max_names <= 0) { + return -EINVAL; + } + + int count = 0; + for (int i = 0; i < sensor_count && count < max_names; i++) { + if (sensors[i].in_use) { + name_list[count] = (char *)sensors[i].info.sensor_name; + count++; + } + } + + return count; } diff --git a/src/runtime/wamr/ocre_api/ocre_sensors/ocre_sensors.h b/src/runtime/wamr/ocre_api/ocre_sensors/ocre_sensors.h index badad07b..31059638 100644 --- a/src/runtime/wamr/ocre_api/ocre_sensors/ocre_sensors.h +++ b/src/runtime/wamr/ocre_api/ocre_sensors/ocre_sensors.h @@ -19,25 +19,25 @@ typedef int32_t ocre_sensor_handle_t; * @brief Enum representing different sensor channels */ typedef enum { - SENSOR_CHANNEL_ACCELERATION, - SENSOR_CHANNEL_GYRO, - SENSOR_CHANNEL_MAGNETIC_FIELD, - SENSOR_CHANNEL_LIGHT, - SENSOR_CHANNEL_PRESSURE, - SENSOR_CHANNEL_PROXIMITY, - SENSOR_CHANNEL_HUMIDITY, - SENSOR_CHANNEL_TEMPERATURE, - // Add more channels as needed + SENSOR_CHANNEL_ACCELERATION, + SENSOR_CHANNEL_GYRO, + SENSOR_CHANNEL_MAGNETIC_FIELD, + SENSOR_CHANNEL_LIGHT, + SENSOR_CHANNEL_PRESSURE, + SENSOR_CHANNEL_PROXIMITY, + SENSOR_CHANNEL_HUMIDITY, + SENSOR_CHANNEL_TEMPERATURE, + // Add more channels as needed } sensor_channel_t; /** * @brief Structure representing a sensor instance */ typedef struct ocre_sensor_t { - ocre_sensor_handle_t handle; - char sensor_name[CONFIG_MAX_SENSOR_NAME_LENGTH]; - int num_channels; - enum sensor_channel channels[CONFIG_MAX_CHANNELS_PER_SENSOR]; + ocre_sensor_handle_t handle; + char sensor_name[CONFIG_MAX_SENSOR_NAME_LENGTH]; + int num_channels; + enum sensor_channel channels[CONFIG_MAX_CHANNELS_PER_SENSOR]; } ocre_sensor_t; /** * @brief Initialize the sensor system diff --git a/src/runtime/wamr/ocre_api/ocre_sensors/rng_sensor.c b/src/runtime/wamr/ocre_api/ocre_sensors/rng_sensor.c index c172b59e..22acc6df 100644 --- a/src/runtime/wamr/ocre_api/ocre_sensors/rng_sensor.c +++ b/src/runtime/wamr/ocre_api/ocre_sensors/rng_sensor.c @@ -14,53 +14,56 @@ /* Define the sensor channels */ static enum sensor_channel rng_sensor_channels[] __attribute__((unused)) = { - SENSOR_CHAN_CUSTOM + 1, /* Define a custom channel */ + SENSOR_CHAN_CUSTOM + 1, /* Define a custom channel */ }; /* Define the sensor data structure */ struct rng_sensor_data { - struct sensor_value value; + struct sensor_value value; }; /* Define the sensor driver API functions */ /* Function to get sensor data */ -static int rng_sensor_sample_fetch(const struct device *dev, enum sensor_channel chan) { - struct rng_sensor_data *data = dev->data; +static int rng_sensor_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + struct rng_sensor_data *data = dev->data; - /* Generate a random 32-bit number */ - uint32_t random_number = sys_rand16_get(); + /* Generate a random 32-bit number */ + uint32_t random_number = sys_rand16_get(); - /* Store the random number in sensor_value */ - data->value.val1 = random_number; /* Integer part */ - data->value.val2 = 0; /* Fractional part */ + /* Store the random number in sensor_value */ + data->value.val1 = random_number; /* Integer part */ + data->value.val2 = 0; /* Fractional part */ - return 0; + return 0; } /* Function to retrieve sensor data */ -static int rng_sensor_channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) { - struct rng_sensor_data *data = dev->data; +static int rng_sensor_channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) +{ + struct rng_sensor_data *data = dev->data; - if (chan != SENSOR_CHAN_CUSTOM + 1) { - return -ENOTSUP; - } + if (chan != SENSOR_CHAN_CUSTOM + 1) { + return -ENOTSUP; + } - *val = data->value; + *val = data->value; - return 0; + return 0; } /* Define the sensor driver API */ static const struct sensor_driver_api rng_sensor_api = { - .sample_fetch = rng_sensor_sample_fetch, - .channel_get = rng_sensor_channel_get, + .sample_fetch = rng_sensor_sample_fetch, + .channel_get = rng_sensor_channel_get, }; /* Initialization function */ -int rng_sensor_init(const struct device *dev) { - /* Initialization code if needed */ - return 0; +int rng_sensor_init(const struct device *dev) +{ + /* Initialization code if needed */ + return 0; } // /* Define the sensor device */ @@ -68,5 +71,5 @@ int rng_sensor_init(const struct device *dev) { static struct rng_sensor_data rng_sensor_data; DEVICE_DT_DEFINE(DT_DRV_INST(0), rng_sensor_init, NULL, &rng_sensor_data, NULL, POST_KERNEL, - CONFIG_SENSOR_INIT_PRIORITY, &rng_sensor_api); + CONFIG_SENSOR_INIT_PRIORITY, &rng_sensor_api); #endif diff --git a/src/samples/demo/main.c b/src/samples/demo/main.c index a90689ab..58a4ef74 100644 --- a/src/samples/demo/main.c +++ b/src/samples/demo/main.c @@ -101,7 +101,6 @@ int main(int argc, char *argv[]) return 1; } - rc = ocre_container_start(publisher); if (rc) { fprintf(stderr, "Failed to start container\n"); diff --git a/src/samples/mini/main.c b/src/samples/mini/main.c index 916f4944..8125237f 100644 --- a/src/samples/mini/main.c +++ b/src/samples/mini/main.c @@ -78,8 +78,7 @@ int main(int argc, char *argv[]) free(sample_path); return 1; } - } - else { + } else { fprintf(stderr, "Sample file '%s' already exists\n", sample_path); } @@ -109,10 +108,10 @@ int main(int argc, char *argv[]) ocre_deinitialize(); -/* Exit simulator on zephyr */ + /* Exit simulator on zephyr */ #ifdef CONFIG_ARCH_POSIX - nsi_exit(0); + nsi_exit(0); #endif return 0; diff --git a/src/samples/supervisor/zephyr/download_file.c b/src/samples/supervisor/zephyr/download_file.c index bc947f59..55690c0e 100644 --- a/src/samples/supervisor/zephyr/download_file.c +++ b/src/samples/supervisor/zephyr/download_file.c @@ -67,10 +67,10 @@ int ocre_download_file(const char *url, const char *filepath) if (!strncmp("http", url + parsed_url.field_data[UF_SCHEMA].off, parsed_url.field_data[UF_SCHEMA].len)) { port = 80; strcpy(port_str, "80"); - // } else if (!strncmp("https", url + parsed_url.field_data[UF_SCHEMA].off, - // parsed_url.field_data[UF_SCHEMA].len)) { - // port = 443; - // strcpy(port_str, "443"); + // } else if (!strncmp("https", url + parsed_url.field_data[UF_SCHEMA].off, + // parsed_url.field_data[UF_SCHEMA].len)) { + // port = 443; + // strcpy(port_str, "443"); } else { fprintf(stderr, "Unsupported URL schema: '%s'", url + parsed_url.field_data[UF_SCHEMA].off); goto finish; diff --git a/src/shell/container/create.c b/src/shell/container/create.c index 9e2b0e9a..929250c2 100644 --- a/src/shell/container/create.c +++ b/src/shell/container/create.c @@ -116,7 +116,8 @@ int cmd_container_create_run(struct ocre_context *ctx, char *argv0, int argc, ch dst++; if (dst[0] != '/') { - fprintf(stderr, "Invalid mount format: '%s': destination must be absolute path\n", + fprintf(stderr, + "Invalid mount format: '%s': destination must be absolute path\n", optarg); goto cleanup; } diff --git a/src/shell/container/kill.c b/src/shell/container/kill.c index 57d21438..7ae6f6b5 100644 --- a/src/shell/container/kill.c +++ b/src/shell/container/kill.c @@ -15,22 +15,22 @@ static int usage(const char *argv0) int cmd_container_kill(struct ocre_context *ctx, char *argv0, int argc, char **argv) { if (argc == 2) { - struct ocre_container *container = ocre_context_get_container_by_id(ctx, argv[1]); - if (!container) { - fprintf(stderr, "Failed to get container '%s'\n", argv[1]); - return -1; - } + struct ocre_container *container = ocre_context_get_container_by_id(ctx, argv[1]); + if (!container) { + fprintf(stderr, "Failed to get container '%s'\n", argv[1]); + return -1; + } - if (ocre_container_get_status(container) != OCRE_CONTAINER_STATUS_RUNNING) { - fprintf(stderr, "Container '%s' is not running\n", argv[1]); - return -1; - } + if (ocre_container_get_status(container) != OCRE_CONTAINER_STATUS_RUNNING) { + fprintf(stderr, "Container '%s' is not running\n", argv[1]); + return -1; + } - int rc = ocre_container_kill(container); + int rc = ocre_container_kill(container); - fprintf(stdout, "%s\n", argv[1]); + fprintf(stdout, "%s\n", argv[1]); - return rc; + return rc; } else { fprintf(stderr, "'%s container kill' requires exactly one argument\n\n", argv0); return usage(argv0); diff --git a/src/shell/container/ps.c b/src/shell/container/ps.c index 7455e1d2..032dd1d7 100644 --- a/src/shell/container/ps.c +++ b/src/shell/container/ps.c @@ -6,15 +6,7 @@ #include "../command.h" -static const char *container_statuses[] = { - "UNKNOWN", - "CREATED", - "RUNNING", - "PAUSED ", - "EXITED ", - "STOPPED", - "ERROR " -}; +static const char *container_statuses[] = {"UNKNOWN", "CREATED", "RUNNING", "PAUSED ", "EXITED ", "STOPPED", "ERROR "}; static int usage(const char *argv0) { @@ -30,13 +22,13 @@ static void header(void) static int list_container(struct ocre_container *container) { - const char *id = ocre_container_get_id(container); - const char *image = ocre_container_get_image(container); - ocre_container_status_t status = ocre_container_get_status(container); + const char *id = ocre_container_get_id(container); + const char *image = ocre_container_get_image(container); + ocre_container_status_t status = ocre_container_get_status(container); - if (!id || !image || status == OCRE_CONTAINER_STATUS_UNKNOWN) { - return -1; - } + if (!id || !image || status == OCRE_CONTAINER_STATUS_UNKNOWN) { + return -1; + } printf("%s\t%s\t%s\n", id, container_statuses[status], image); @@ -45,7 +37,7 @@ static int list_container(struct ocre_container *container) static int list_containers(struct ocre_context *ctx) { - int ret = -1; + int ret = -1; int num_containers = ocre_context_get_num_containers(ctx); if (num_containers < 0) { fprintf(stderr, "Failed to get number of containers\n"); diff --git a/src/shell/container/start.c b/src/shell/container/start.c index 473c9af8..4f226f5b 100644 --- a/src/shell/container/start.c +++ b/src/shell/container/start.c @@ -15,23 +15,23 @@ static int usage(const char *argv0) int cmd_container_start(struct ocre_context *ctx, char *argv0, int argc, char **argv) { if (argc == 2) { - struct ocre_container *container = ocre_context_get_container_by_id(ctx, argv[1]); - if (!container) { - fprintf(stderr, "Failed to get container '%s'\n", argv[1]); - return -1; - } - - ocre_container_status_t status = ocre_container_get_status(container); - if (status != OCRE_CONTAINER_STATUS_CREATED && status != OCRE_CONTAINER_STATUS_STOPPED) { - fprintf(stderr, "Container '%s' is not ready to run\n", argv[1]); - return -1; - } + struct ocre_container *container = ocre_context_get_container_by_id(ctx, argv[1]); + if (!container) { + fprintf(stderr, "Failed to get container '%s'\n", argv[1]); + return -1; + } + + ocre_container_status_t status = ocre_container_get_status(container); + if (status != OCRE_CONTAINER_STATUS_CREATED && status != OCRE_CONTAINER_STATUS_STOPPED) { + fprintf(stderr, "Container '%s' is not ready to run\n", argv[1]); + return -1; + } - int rc = ocre_container_start(container); + int rc = ocre_container_start(container); - fprintf(stdout, "%s\n", argv[1]); + fprintf(stdout, "%s\n", argv[1]); - return rc; + return rc; } else { fprintf(stderr, "'%s container start' requires exactly one argument\n\n", argv0); return usage(argv0); diff --git a/src/shell/container/wait.c b/src/shell/container/wait.c index 90455878..1deb886b 100644 --- a/src/shell/container/wait.c +++ b/src/shell/container/wait.c @@ -15,28 +15,28 @@ static int usage(const char *argv0) int cmd_container_wait(struct ocre_context *ctx, char *argv0, int argc, char **argv) { if (argc == 2) { - struct ocre_container *container = ocre_context_get_container_by_id(ctx, argv[1]); - if (!container) { - fprintf(stderr, "Failed to get container '%s'\n", argv[1]); - return -1; - } - - ocre_container_status_t status = ocre_container_get_status(container); - if (status == OCRE_CONTAINER_STATUS_UNKNOWN || status == OCRE_CONTAINER_STATUS_CREATED) { - fprintf(stderr, "Container '%s' has not started\n", argv[1]); - return -1; - } - - int return_code; - int rc = ocre_container_wait(container, &return_code); - if (rc) { - fprintf(stderr, "Failed to wait for container '%s'\n", argv[1]); - return -1; - } - - fprintf(stdout, "%d\n", return_code); - - return rc; + struct ocre_container *container = ocre_context_get_container_by_id(ctx, argv[1]); + if (!container) { + fprintf(stderr, "Failed to get container '%s'\n", argv[1]); + return -1; + } + + ocre_container_status_t status = ocre_container_get_status(container); + if (status == OCRE_CONTAINER_STATUS_UNKNOWN || status == OCRE_CONTAINER_STATUS_CREATED) { + fprintf(stderr, "Container '%s' has not started\n", argv[1]); + return -1; + } + + int return_code; + int rc = ocre_container_wait(container, &return_code); + if (rc) { + fprintf(stderr, "Failed to wait for container '%s'\n", argv[1]); + return -1; + } + + fprintf(stdout, "%d\n", return_code); + + return rc; } else { fprintf(stderr, "'%s container wait' requires exactly one argument\n\n", argv0); return usage(argv0); diff --git a/src/shell/sha256/sha256.c b/src/shell/sha256/sha256.c index 9fef5925..f3fcec33 100644 --- a/src/shell/sha256/sha256.c +++ b/src/shell/sha256/sha256.c @@ -27,156 +27,165 @@ #include "sha256.h" -void sha256_init(struct sha256_buff* buff) { - buff->h[0] = 0x6a09e667; - buff->h[1] = 0xbb67ae85; - buff->h[2] = 0x3c6ef372; - buff->h[3] = 0xa54ff53a; - buff->h[4] = 0x510e527f; - buff->h[5] = 0x9b05688c; - buff->h[6] = 0x1f83d9ab; - buff->h[7] = 0x5be0cd19; - buff->data_size = 0; - buff->chunk_size = 0; +void sha256_init(struct sha256_buff *buff) +{ + buff->h[0] = 0x6a09e667; + buff->h[1] = 0xbb67ae85; + buff->h[2] = 0x3c6ef372; + buff->h[3] = 0xa54ff53a; + buff->h[4] = 0x510e527f; + buff->h[5] = 0x9b05688c; + buff->h[6] = 0x1f83d9ab; + buff->h[7] = 0x5be0cd19; + buff->data_size = 0; + buff->chunk_size = 0; } static const uint32_t k[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}; #define rotate_r(val, bits) (val >> bits | val << (32 - bits)) -static void sha256_calc_chunk(struct sha256_buff* buff, const uint8_t* chunk) { - uint32_t w[64]; - uint32_t tv[8]; - uint32_t i; - - for (i=0; i<16; ++i){ - w[i] = (uint32_t) chunk[0] << 24 | (uint32_t) chunk[1] << 16 | (uint32_t) chunk[2] << 8 | (uint32_t) chunk[3]; - chunk += 4; - } - - for (i=16; i<64; ++i){ - uint32_t s0 = rotate_r(w[i-15], 7) ^ rotate_r(w[i-15], 18) ^ (w[i-15] >> 3); - uint32_t s1 = rotate_r(w[i-2], 17) ^ rotate_r(w[i-2], 19) ^ (w[i-2] >> 10); - w[i] = w[i-16] + s0 + w[i-7] + s1; - } - - for (i = 0; i < 8; ++i) - tv[i] = buff->h[i]; - - for (i=0; i<64; ++i){ - uint32_t S1 = rotate_r(tv[4], 6) ^ rotate_r(tv[4], 11) ^ rotate_r(tv[4], 25); - uint32_t ch = (tv[4] & tv[5]) ^ (~tv[4] & tv[6]); - uint32_t temp1 = tv[7] + S1 + ch + k[i] + w[i]; - uint32_t S0 = rotate_r(tv[0], 2) ^ rotate_r(tv[0], 13) ^ rotate_r(tv[0], 22); - uint32_t maj = (tv[0] & tv[1]) ^ (tv[0] & tv[2]) ^ (tv[1] & tv[2]); - uint32_t temp2 = S0 + maj; - - tv[7] = tv[6]; - tv[6] = tv[5]; - tv[5] = tv[4]; - tv[4] = tv[3] + temp1; - tv[3] = tv[2]; - tv[2] = tv[1]; - tv[1] = tv[0]; - tv[0] = temp1 + temp2; - } - - for (i = 0; i < 8; ++i) - buff->h[i] += tv[i]; +static void sha256_calc_chunk(struct sha256_buff *buff, const uint8_t *chunk) +{ + uint32_t w[64]; + uint32_t tv[8]; + uint32_t i; + + for (i = 0; i < 16; ++i) { + w[i] = (uint32_t)chunk[0] << 24 | (uint32_t)chunk[1] << 16 | (uint32_t)chunk[2] << 8 | + (uint32_t)chunk[3]; + chunk += 4; + } + + for (i = 16; i < 64; ++i) { + uint32_t s0 = rotate_r(w[i - 15], 7) ^ rotate_r(w[i - 15], 18) ^ (w[i - 15] >> 3); + uint32_t s1 = rotate_r(w[i - 2], 17) ^ rotate_r(w[i - 2], 19) ^ (w[i - 2] >> 10); + w[i] = w[i - 16] + s0 + w[i - 7] + s1; + } + + for (i = 0; i < 8; ++i) + tv[i] = buff->h[i]; + + for (i = 0; i < 64; ++i) { + uint32_t S1 = rotate_r(tv[4], 6) ^ rotate_r(tv[4], 11) ^ rotate_r(tv[4], 25); + uint32_t ch = (tv[4] & tv[5]) ^ (~tv[4] & tv[6]); + uint32_t temp1 = tv[7] + S1 + ch + k[i] + w[i]; + uint32_t S0 = rotate_r(tv[0], 2) ^ rotate_r(tv[0], 13) ^ rotate_r(tv[0], 22); + uint32_t maj = (tv[0] & tv[1]) ^ (tv[0] & tv[2]) ^ (tv[1] & tv[2]); + uint32_t temp2 = S0 + maj; + + tv[7] = tv[6]; + tv[6] = tv[5]; + tv[5] = tv[4]; + tv[4] = tv[3] + temp1; + tv[3] = tv[2]; + tv[2] = tv[1]; + tv[1] = tv[0]; + tv[0] = temp1 + temp2; + } + + for (i = 0; i < 8; ++i) + buff->h[i] += tv[i]; } -void sha256_update(struct sha256_buff* buff, const void* data, size_t size) { - const uint8_t* ptr = (const uint8_t*)data; - buff->data_size += size; - /* If there is data left in buff, concatenate it to process as new chunk */ - if (size + buff->chunk_size >= 64) { - uint8_t tmp_chunk[64]; - memcpy(tmp_chunk, buff->last_chunk, buff->chunk_size); - memcpy(tmp_chunk + buff->chunk_size, ptr, 64 - buff->chunk_size); - ptr += (64 - buff->chunk_size); - size -= (64 - buff->chunk_size); - buff->chunk_size = 0; - sha256_calc_chunk(buff, tmp_chunk); - } - /* Run over data chunks */ - while (size >= 64) { - sha256_calc_chunk(buff, ptr); - ptr += 64; - size -= 64; - } - - /* Save remaining data in buff, will be reused on next call or finalize */ - memcpy(buff->last_chunk + buff->chunk_size, ptr, size); - buff->chunk_size += size; +void sha256_update(struct sha256_buff *buff, const void *data, size_t size) +{ + const uint8_t *ptr = (const uint8_t *)data; + buff->data_size += size; + /* If there is data left in buff, concatenate it to process as new chunk */ + if (size + buff->chunk_size >= 64) { + uint8_t tmp_chunk[64]; + memcpy(tmp_chunk, buff->last_chunk, buff->chunk_size); + memcpy(tmp_chunk + buff->chunk_size, ptr, 64 - buff->chunk_size); + ptr += (64 - buff->chunk_size); + size -= (64 - buff->chunk_size); + buff->chunk_size = 0; + sha256_calc_chunk(buff, tmp_chunk); + } + /* Run over data chunks */ + while (size >= 64) { + sha256_calc_chunk(buff, ptr); + ptr += 64; + size -= 64; + } + + /* Save remaining data in buff, will be reused on next call or finalize */ + memcpy(buff->last_chunk + buff->chunk_size, ptr, size); + buff->chunk_size += size; } -void sha256_finalize(struct sha256_buff* buff) { - buff->last_chunk[buff->chunk_size] = 0x80; - buff->chunk_size++; - memset(buff->last_chunk + buff->chunk_size, 0, 64 - buff->chunk_size); - - /* If there isn't enough space to fit int64, pad chunk with zeroes and prepare next chunk */ - if (buff->chunk_size > 56) { - sha256_calc_chunk(buff, buff->last_chunk); - memset(buff->last_chunk, 0, 64); - } - - /* Add total size as big-endian int64 x8 */ - uint64_t size = buff->data_size * 8; - int i; - for (i = 8; i > 0; --i) { - buff->last_chunk[55+i] = size & 255; - size >>= 8; - } - - sha256_calc_chunk(buff, buff->last_chunk); +void sha256_finalize(struct sha256_buff *buff) +{ + buff->last_chunk[buff->chunk_size] = 0x80; + buff->chunk_size++; + memset(buff->last_chunk + buff->chunk_size, 0, 64 - buff->chunk_size); + + /* If there isn't enough space to fit int64, pad chunk with zeroes and prepare next chunk */ + if (buff->chunk_size > 56) { + sha256_calc_chunk(buff, buff->last_chunk); + memset(buff->last_chunk, 0, 64); + } + + /* Add total size as big-endian int64 x8 */ + uint64_t size = buff->data_size * 8; + int i; + for (i = 8; i > 0; --i) { + buff->last_chunk[55 + i] = size & 255; + size >>= 8; + } + + sha256_calc_chunk(buff, buff->last_chunk); } -void sha256_read(const struct sha256_buff* buff, uint8_t* hash) { - uint32_t i; - for (i = 0; i < 8; i++) { - hash[i*4] = (buff->h[i] >> 24) & 255; - hash[i*4 + 1] = (buff->h[i] >> 16) & 255; - hash[i*4 + 2] = (buff->h[i] >> 8) & 255; - hash[i*4 + 3] = buff->h[i] & 255; - } +void sha256_read(const struct sha256_buff *buff, uint8_t *hash) +{ + uint32_t i; + for (i = 0; i < 8; i++) { + hash[i * 4] = (buff->h[i] >> 24) & 255; + hash[i * 4 + 1] = (buff->h[i] >> 16) & 255; + hash[i * 4 + 2] = (buff->h[i] >> 8) & 255; + hash[i * 4 + 3] = buff->h[i] & 255; + } } -static void bin_to_hex(const void* data, uint32_t len, char* out) { - static const char* const lut = "0123456789abcdef"; - uint32_t i; - for (i = 0; i < len; ++i){ - uint8_t c = ((const uint8_t*)data)[i]; - out[i*2] = lut[c >> 4]; - out[i*2 + 1] = lut[c & 15]; - } +static void bin_to_hex(const void *data, uint32_t len, char *out) +{ + static const char *const lut = "0123456789abcdef"; + uint32_t i; + for (i = 0; i < len; ++i) { + uint8_t c = ((const uint8_t *)data)[i]; + out[i * 2] = lut[c >> 4]; + out[i * 2 + 1] = lut[c & 15]; + } } -void sha256_read_hex(const struct sha256_buff* buff, char* hex) { - uint8_t hash[32]; - sha256_read(buff, hash); - bin_to_hex(hash, 32, hex); +void sha256_read_hex(const struct sha256_buff *buff, char *hex) +{ + uint8_t hash[32]; + sha256_read(buff, hash); + bin_to_hex(hash, 32, hex); } -void sha256_easy_hash(const void* data, size_t size, uint8_t* hash) { - struct sha256_buff buff; - sha256_init(&buff); - sha256_update(&buff, data, size); - sha256_finalize(&buff); - sha256_read(&buff, hash); +void sha256_easy_hash(const void *data, size_t size, uint8_t *hash) +{ + struct sha256_buff buff; + sha256_init(&buff); + sha256_update(&buff, data, size); + sha256_finalize(&buff); + sha256_read(&buff, hash); } -void sha256_easy_hash_hex(const void* data, size_t size, char* hex) { - uint8_t hash[32]; - sha256_easy_hash(data, size, hash); - bin_to_hex(hash, 32, hex); +void sha256_easy_hash_hex(const void *data, size_t size, char *hex) +{ + uint8_t hash[32]; + sha256_easy_hash(data, size, hash); + bin_to_hex(hash, 32, hex); } diff --git a/src/shell/sha256/sha256.h b/src/shell/sha256/sha256.h index a419b23e..a64b6d7c 100644 --- a/src/shell/sha256/sha256.h +++ b/src/shell/sha256/sha256.h @@ -25,75 +25,37 @@ #ifndef SHA256_H #define SHA256_H -#ifdef __cplusplus -extern "C" { -#endif - #include #include #include struct sha256_buff { - uint64_t data_size; - uint32_t h[8]; - uint8_t last_chunk[64]; - uint8_t chunk_size; + uint64_t data_size; + uint32_t h[8]; + uint8_t last_chunk[64]; + uint8_t chunk_size; }; /* Initialization, must be called before any further use */ -void sha256_init(struct sha256_buff* buff); +void sha256_init(struct sha256_buff *buff); /* Process block of data of arbitary length, can be used on data streams (files, etc) */ -void sha256_update(struct sha256_buff* buff, const void* data, size_t size); +void sha256_update(struct sha256_buff *buff, const void *data, size_t size); /* Produces final hash values (digest) to be read If the buffer is reused later, init must be called again */ -void sha256_finalize(struct sha256_buff* buff); +void sha256_finalize(struct sha256_buff *buff); /* Read digest into 32-byte binary array */ -void sha256_read(const struct sha256_buff* buff, uint8_t* hash); +void sha256_read(const struct sha256_buff *buff, uint8_t *hash); /* Read digest into 64-char string as hex (without null-byte) */ -void sha256_read_hex(const struct sha256_buff* buff, char* hex); +void sha256_read_hex(const struct sha256_buff *buff, char *hex); /* Hashes single contiguous block of data and reads digest into 32-byte binary array */ -void sha256_easy_hash(const void* data, size_t size, uint8_t* hash); +void sha256_easy_hash(const void *data, size_t size, uint8_t *hash); /* Hashes single contiguous block of data and reads digest into 64-char string (without null-byte) */ -void sha256_easy_hash_hex(const void* data, size_t size, char* hex); - -#ifdef __cplusplus -} - -#include - -class SHA256 { -private: - struct sha256_buff buff; -public: - SHA256() { - sha256_init(&buff); - } - - void update(const void* data, std::size_t size) { - sha256_update(&buff, data, size); - } - - std::string hash() { - char hash[64]; - sha256_finalize(&buff); - sha256_read_hex(&buff, hash); - sha256_init(&buff); - return std::string(hash, 64); - } - - static std::string hashString(const std::string& str) { - char hash[64]; - sha256_easy_hash_hex(str.c_str(), str.length(), hash); - return std::string(hash, 64); - } -}; - -#endif +void sha256_easy_hash_hex(const void *data, size_t size, char *hex); #endif From 8d1f08e53093e69a472d6ad89c726e33a0780d2c Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 11:51:57 +0100 Subject: [PATCH 160/234] chore(ocre_api): remove unused functions They are not needed anymore. Signed-off-by: Marco Casaroli --- src/runtime/wamr/ocre_api/CMakeLists.txt | 1 - .../wamr/ocre_api/core/core_external.h | 12 ------ .../wamr/ocre_api/core/core_internal.h | 24 ------------ src/runtime/wamr/ocre_api/core/core_misc.c | 27 ------------- src/runtime/wamr/ocre_api/core/core_slist.c | 38 ------------------- src/runtime/wamr/ocre_api/ocre_common.c | 1 - 6 files changed, 103 deletions(-) delete mode 100644 src/runtime/wamr/ocre_api/core/core_slist.c diff --git a/src/runtime/wamr/ocre_api/CMakeLists.txt b/src/runtime/wamr/ocre_api/CMakeLists.txt index 156199e8..f4d40a14 100644 --- a/src/runtime/wamr/ocre_api/CMakeLists.txt +++ b/src/runtime/wamr/ocre_api/CMakeLists.txt @@ -11,7 +11,6 @@ target_sources(OcreRuntimeAPI core/core_misc.c core/core_timer.c core/core_mutex.c - core/core_slist.c core/core_memory.c ) diff --git a/src/runtime/wamr/ocre_api/core/core_external.h b/src/runtime/wamr/ocre_api/core/core_external.h index afdd4b7a..b1435174 100644 --- a/src/runtime/wamr/ocre_api/core/core_external.h +++ b/src/runtime/wamr/ocre_api/core/core_external.h @@ -117,13 +117,6 @@ int core_mq_send(core_mq_t *mq, const void *data, size_t msg_len); */ int core_mq_recv(core_mq_t *mq, void *data); -/** - * @brief Sleep for a specified number of milliseconds. - * - * @param milliseconds Number of milliseconds to sleep. - */ -void core_sleep_ms(int milliseconds); - /** * @brief Allocate memory. * @@ -139,11 +132,6 @@ void *core_malloc(size_t size); */ void core_free(void *ptr); -/** - * @brief Yield the current thread's execution. - */ -void core_yield(void); - typedef struct core_timer core_timer_t; /** diff --git a/src/runtime/wamr/ocre_api/core/core_internal.h b/src/runtime/wamr/ocre_api/core/core_internal.h index 114481ba..ba915f37 100644 --- a/src/runtime/wamr/ocre_api/core/core_internal.h +++ b/src/runtime/wamr/ocre_api/core/core_internal.h @@ -111,30 +111,6 @@ typedef struct { core_snode_t *tail; /*!< Pointer to the last node in the list */ } core_slist_t; -/** - * @brief Initialize a singly-linked list. - * - * @param list Pointer to the list to initialize. - */ -void core_slist_init(core_slist_t *list); - -/** - * @brief Append a node to the end of a singly-linked list. - * - * @param list Pointer to the list to append to. - * @param node Pointer to the node to append. - */ -void core_slist_append(core_slist_t *list, core_snode_t *node); - -/** - * @brief Remove a node from a singly-linked list. - * - * @param list Pointer to the list to remove from. - * @param prev Pointer to the previous node (or NULL if removing head). - * @param node Pointer to the node to remove. - */ -void core_slist_remove(core_slist_t *list, core_snode_t *prev, core_snode_t *node); - /** * @brief Spinlock type for POSIX platform (simulated using mutex). */ diff --git a/src/runtime/wamr/ocre_api/core/core_misc.c b/src/runtime/wamr/ocre_api/core/core_misc.c index cf85a8ed..86798ec2 100644 --- a/src/runtime/wamr/ocre_api/core/core_misc.c +++ b/src/runtime/wamr/ocre_api/core/core_misc.c @@ -13,33 +13,6 @@ #include #include -void core_sleep_ms(int milliseconds) -{ - struct timespec ts; - int res; - - if (milliseconds < 0) { - errno = EINVAL; - fprintf(stderr, "core_sleep_ms: Invalid milliseconds value (%d)\n", milliseconds); - return; - } - - ts.tv_sec = milliseconds / 1000; - ts.tv_nsec = (milliseconds % 1000) * 1000000; - - do { - res = nanosleep(&ts, &ts); - if (res && errno != EINTR) { - fprintf(stderr, "core_sleep_ms: nanosleep failed (errno=%d)\n", errno); - } - } while (res && errno == EINTR); -} - -void core_yield(void) -{ - sched_yield(); -} - uint32_t core_uptime_get(void) { struct timespec ts; diff --git a/src/runtime/wamr/ocre_api/core/core_slist.c b/src/runtime/wamr/ocre_api/core/core_slist.c deleted file mode 100644 index 2f87fe1d..00000000 --- a/src/runtime/wamr/ocre_api/core/core_slist.c +++ /dev/null @@ -1,38 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include "core_external.h" - -void core_slist_init(core_slist_t *list) -{ - list->head = NULL; - list->tail = NULL; -} - -void core_slist_append(core_slist_t *list, core_snode_t *node) -{ - node->next = NULL; - if (list->tail) { - list->tail->next = node; - } else { - list->head = node; - } - list->tail = node; -} - -void core_slist_remove(core_slist_t *list, core_snode_t *prev, core_snode_t *node) -{ - if (prev) { - prev->next = node->next; - } else { - list->head = node->next; - } - if (list->tail == node) { - list->tail = prev; - } -} diff --git a/src/runtime/wamr/ocre_api/ocre_common.c b/src/runtime/wamr/ocre_api/ocre_common.c index 85263a34..b527242c 100644 --- a/src/runtime/wamr/ocre_api/ocre_common.c +++ b/src/runtime/wamr/ocre_api/ocre_common.c @@ -5,7 +5,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -// #include #include #include #include From b06959080e4ad6268cfb285ef876fc4b2562a6ff Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 13:12:25 +0100 Subject: [PATCH 161/234] fix: cppcheck warnings Signed-off-by: Marco Casaroli --- src/ocre/context.c | 4 +-- src/ocre/include/ocre/ocre.h | 2 +- src/ocre/util/rm_rf.c | 2 +- src/platform/posix/file_mmap.c | 2 +- src/runtime/wamr/wamr.c | 52 +--------------------------------- src/shell/command.h | 2 +- src/shell/container.c | 10 +++---- src/shell/container.h | 2 +- src/shell/container/create.c | 35 +++++++++++++++++------ src/shell/container/create.h | 2 +- src/shell/container/kill.c | 2 +- src/shell/container/kill.h | 2 +- src/shell/container/pause.c | 2 +- src/shell/container/pause.h | 2 +- src/shell/container/ps.c | 2 +- src/shell/container/ps.h | 2 +- src/shell/container/rm.c | 2 +- src/shell/container/rm.h | 2 +- src/shell/container/start.c | 2 +- src/shell/container/start.h | 2 +- src/shell/container/stop.c | 2 +- src/shell/container/stop.h | 2 +- src/shell/container/unpause.c | 2 +- src/shell/container/unpause.h | 2 +- src/shell/container/wait.c | 2 +- src/shell/container/wait.h | 2 +- src/shell/image.c | 4 +-- src/shell/image.h | 2 +- src/shell/image/ls.c | 4 +-- src/shell/image/ls.h | 2 +- src/shell/image/pull.c | 4 +-- src/shell/image/pull.h | 2 +- src/shell/image/rm.c | 2 +- src/shell/image/rm.h | 2 +- src/shell/shell.c | 10 +++---- 35 files changed, 73 insertions(+), 104 deletions(-) diff --git a/src/ocre/context.c b/src/ocre/context.c index e9d14640..f0f1179e 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -38,7 +38,7 @@ static int delete_container_workdirs(const char *working_directory) { int ret = -1; DIR *d = NULL; - struct dirent *dir = NULL; + const struct dirent *dir = NULL; char *containers_path = malloc(strlen(working_directory) + strlen("/containers") + 1); if (!containers_path) { @@ -510,7 +510,7 @@ int ocre_context_get_num_containers(struct ocre_context *context) return count; } -const char *ocre_context_get_working_directory(struct ocre_context *context) +const char *ocre_context_get_working_directory(const struct ocre_context *context) { /* We never change this, no need to lock */ diff --git a/src/ocre/include/ocre/ocre.h b/src/ocre/include/ocre/ocre.h index 6081c654..7075eca1 100644 --- a/src/ocre/include/ocre/ocre.h +++ b/src/ocre/include/ocre/ocre.h @@ -328,7 +328,7 @@ int ocre_context_list_containers(struct ocre_context *context, struct ocre_conta * * @return A pointer to the working directory string, or NULL on failure */ -const char *ocre_context_get_working_directory(struct ocre_context *context); +const char *ocre_context_get_working_directory(const struct ocre_context *context); /** * @brief Check if a container or image ID is valid diff --git a/src/ocre/util/rm_rf.c b/src/ocre/util/rm_rf.c index d91ca627..a40b3031 100644 --- a/src/ocre/util/rm_rf.c +++ b/src/ocre/util/rm_rf.c @@ -136,7 +136,7 @@ int rm_rf(const char *path) /* Read next directory entry */ - struct dirent *entry = readdir(current->dir); + const struct dirent *entry = readdir(current->dir); if (!entry) { /* No more entries, mark for removal and continue */ current->is_removal_phase = 1; diff --git a/src/platform/posix/file_mmap.c b/src/platform/posix/file_mmap.c index 384a01ad..3ff927c8 100644 --- a/src/platform/posix/file_mmap.c +++ b/src/platform/posix/file_mmap.c @@ -14,7 +14,7 @@ LOG_MODULE_REGISTER(file_mmap, CONFIG_OCRE_LOG_LEVEL); void *ocre_load_file(const char *path, size_t *size) { - int save_errno = 0; + int save_errno; void *buffer = NULL; if (!path) { diff --git a/src/runtime/wamr/wamr.c b/src/runtime/wamr/wamr.c index 26eebb18..47693dc1 100644 --- a/src/runtime/wamr/wamr.c +++ b/src/runtime/wamr/wamr.c @@ -313,7 +313,7 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s goto error; } - char *src_colon = strchr(*mount, ':'); + const char *src_colon = strchr(*mount, ':'); if (!src_colon) { LOG_ERR("Invalid mount format: %s", *mount); goto error; @@ -380,14 +380,6 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s error_module: wasm_runtime_unload(context->module); -error_buffer: - ocre_unload_file(context->buffer, context->size); - context->buffer = NULL; - -error_argv: - free(context->argv[0]); - free(context->argv); - error: for (char **dir_map = dir_map_list; dir_map && *dir_map; dir_map++) { free(*dir_map); @@ -419,19 +411,6 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s return NULL; } -static int instance_stop(void *runtime_context) -{ - struct wamr_context *context = runtime_context; - - if (!context) { - return -1; - } - - // TODO - - return -1; -} - static int instance_kill(void *runtime_context) { struct wamr_context *context = runtime_context; @@ -445,32 +424,6 @@ static int instance_kill(void *runtime_context) return 0; } -static int instance_pause(void *runtime_context) -{ - struct wamr_context *context = runtime_context; - - if (!context) { - return -1; - } - - // TODO - - return -1; -} - -static int instance_unpause(void *runtime_context) -{ - struct wamr_context *context = runtime_context; - - if (!context) { - return -1; - } - - // TODO - - return -1; -} - static int instance_destroy(void *runtime_context) { struct wamr_context *context = runtime_context; @@ -510,7 +463,4 @@ const struct ocre_runtime_vtable wamr_vtable = { .destroy = instance_destroy, .thread_execute = instance_thread_execute, .kill = instance_kill, - // .stop = instance_stop, - // .pause = instance_pause, - // .unpause = instance_unpause, }; diff --git a/src/shell/command.h b/src/shell/command.h index f4a75dae..4059e5b7 100644 --- a/src/shell/command.h +++ b/src/shell/command.h @@ -2,5 +2,5 @@ struct ocre_command { char *name; - int (*func)(struct ocre_context *ctx, char *argv0, int argc, char **argv); + int (*func)(struct ocre_context *ctx, const char *argv0, int argc, char **argv); }; diff --git a/src/shell/container.c b/src/shell/container.c index 0680af2f..c49eafdc 100644 --- a/src/shell/container.c +++ b/src/shell/container.c @@ -15,7 +15,7 @@ #include "container/unpause.h" #include "container/wait.h" -static int print_usage(struct ocre_context *ctx, char *argv0, int argc, char **argv) +static int print_usage(struct ocre_context *ctx, const char *argv0, int argc, char **argv) { fprintf(stderr, "Usage: %s container \n", argv0); @@ -38,16 +38,16 @@ static const struct ocre_command commands[] = { {"run", cmd_container_create_run}, {"create", cmd_container_create_run}, {"start", cmd_container_start}, - // {"stop", cmd_container_stop}, + {"stop", cmd_container_stop}, {"kill", cmd_container_kill}, - // {"pause", cmd_container_pause}, - // {"unpause", cmd_container_unpause}, + {"pause", cmd_container_pause}, + {"unpause", cmd_container_unpause}, {"wait", cmd_container_wait}, {"ps", cmd_container_ps}, {"rm", cmd_container_rm}, }; -int cmd_container(struct ocre_context *ctx, char *argv0, int argc, char **argv) +int cmd_container(struct ocre_context *ctx, const char *argv0, int argc, char **argv) { if (argc < 2) { return print_usage(ctx, argv0, argc, argv); diff --git a/src/shell/container.h b/src/shell/container.h index 94058a5d..344a435e 100644 --- a/src/shell/container.h +++ b/src/shell/container.h @@ -1,3 +1,3 @@ #include -int cmd_container(struct ocre_context *ctx, char *argv0, int argc, char **argv); +int cmd_container(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/container/create.c b/src/shell/container/create.c index 929250c2..a50f09ad 100644 --- a/src/shell/container/create.c +++ b/src/shell/container/create.c @@ -8,7 +8,7 @@ #include "../command.h" -static int usage(const char *argv0, char *cmd) +static int usage(const char *argv0, const char *cmd) { fprintf(stderr, "Usage: %s container %s [options] IMAGE [ARG...]\n", argv0, cmd); if (!strcmp(cmd, "create")) { @@ -29,7 +29,7 @@ static int usage(const char *argv0, char *cmd) return -1; } -int cmd_container_create_run(struct ocre_context *ctx, char *argv0, int argc, char **argv) +int cmd_container_create_run(struct ocre_context *ctx, const char *argv0, int argc, char **argv) { int ret = -1; @@ -39,8 +39,8 @@ int cmd_container_create_run(struct ocre_context *ctx, char *argv0, int argc, ch } bool detached = false; - char *runtime = NULL; - char *container_id = NULL; + const char *runtime = NULL; + const char *container_id = NULL; const char **capabilities = NULL; const char **environment = NULL; const char **mounts = NULL; @@ -128,17 +128,36 @@ int cmd_container_create_run(struct ocre_context *ctx, char *argv0, int argc, ch goto cleanup; } - mounts = realloc(mounts, sizeof(char *) * (mounts_count + 1)); + const char **new_mounts = realloc(mounts, sizeof(char *) * (mounts_count + 1)); + if (!new_mounts) { + goto cleanup; + } + + mounts = new_mounts; + mounts[mounts_count++] = optarg; continue; } case 'k': { - capabilities = realloc(capabilities, sizeof(char *) * (capabilities_count + 1)); + const char **new_capabilities = + realloc(capabilities, sizeof(char *) * (capabilities_count + 1)); + if (!new_capabilities) { + goto cleanup; + } + + capabilities = new_capabilities; + capabilities[capabilities_count++] = optarg; continue; } case 'e': { - environment = realloc(environment, sizeof(char *) * (environment_count + 1)); + const char **new_environment = realloc(environment, sizeof(char *) * (environment_count + 1)); + if (!new_environment) { + goto cleanup; + } + + environment = new_environment; + environment[environment_count++] = optarg; continue; } @@ -164,7 +183,7 @@ int cmd_container_create_run(struct ocre_context *ctx, char *argv0, int argc, ch if (optind >= argc) { fprintf(stderr, "'%s container %s' requires at least one non option argument\n\n", argv0, argv[0]); - return usage(argv0, argv[0]); + usage(argv0, argv[0]); goto cleanup; } diff --git a/src/shell/container/create.h b/src/shell/container/create.h index 5822c1ce..9a67f237 100644 --- a/src/shell/container/create.h +++ b/src/shell/container/create.h @@ -1,3 +1,3 @@ #include -int cmd_container_create_run(struct ocre_context *ctx, char *argv0, int argc, char **argv); +int cmd_container_create_run(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/container/kill.c b/src/shell/container/kill.c index 7ae6f6b5..0a4ead00 100644 --- a/src/shell/container/kill.c +++ b/src/shell/container/kill.c @@ -12,7 +12,7 @@ static int usage(const char *argv0) return -1; } -int cmd_container_kill(struct ocre_context *ctx, char *argv0, int argc, char **argv) +int cmd_container_kill(struct ocre_context *ctx, const char *argv0, int argc, char **argv) { if (argc == 2) { struct ocre_container *container = ocre_context_get_container_by_id(ctx, argv[1]); diff --git a/src/shell/container/kill.h b/src/shell/container/kill.h index f239e6d0..f7968a88 100644 --- a/src/shell/container/kill.h +++ b/src/shell/container/kill.h @@ -1,3 +1,3 @@ #include -int cmd_container_kill(struct ocre_context *ctx, char *argv0, int argc, char **argv); +int cmd_container_kill(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/container/pause.c b/src/shell/container/pause.c index 33ae8240..8e84f3e4 100644 --- a/src/shell/container/pause.c +++ b/src/shell/container/pause.c @@ -12,7 +12,7 @@ static int usage(const char *argv0) return -1; } -int cmd_container_pause(struct ocre_context *ctx, char *argv0, int argc, char **argv) +int cmd_container_pause(struct ocre_context *ctx, const char *argv0, int argc, char **argv) { if (argc == 2) { struct ocre_container *container = ocre_context_get_container_by_id(ctx, argv[1]); diff --git a/src/shell/container/pause.h b/src/shell/container/pause.h index 1b8cfc17..b721a786 100644 --- a/src/shell/container/pause.h +++ b/src/shell/container/pause.h @@ -1,3 +1,3 @@ #include -int cmd_container_pause(struct ocre_context *ctx, char *argv0, int argc, char **argv); +int cmd_container_pause(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/container/ps.c b/src/shell/container/ps.c index 032dd1d7..fa70d46d 100644 --- a/src/shell/container/ps.c +++ b/src/shell/container/ps.c @@ -74,7 +74,7 @@ static int list_containers(struct ocre_context *ctx) return ret; } -int cmd_container_ps(struct ocre_context *ctx, char *argv0, int argc, char **argv) +int cmd_container_ps(struct ocre_context *ctx, const char *argv0, int argc, char **argv) { switch (argc) { case 1: { diff --git a/src/shell/container/ps.h b/src/shell/container/ps.h index 7e44a77b..cec6bd23 100644 --- a/src/shell/container/ps.h +++ b/src/shell/container/ps.h @@ -1,3 +1,3 @@ #include -int cmd_container_ps(struct ocre_context *ctx, char *argv0, int argc, char **argv); +int cmd_container_ps(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/container/rm.c b/src/shell/container/rm.c index e5b9341f..43f5a682 100644 --- a/src/shell/container/rm.c +++ b/src/shell/container/rm.c @@ -11,7 +11,7 @@ static int usage(const char *argv0) return -1; } -int cmd_container_rm(struct ocre_context *ctx, char *argv0, int argc, char **argv) +int cmd_container_rm(struct ocre_context *ctx, const char *argv0, int argc, char **argv) { if (argc == 2) { struct ocre_container *container = ocre_context_get_container_by_id(ctx, argv[1]); diff --git a/src/shell/container/rm.h b/src/shell/container/rm.h index 49650208..07a85823 100644 --- a/src/shell/container/rm.h +++ b/src/shell/container/rm.h @@ -1,3 +1,3 @@ #include -int cmd_container_rm(struct ocre_context *ctx, char *argv0, int argc, char **argv); +int cmd_container_rm(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/container/start.c b/src/shell/container/start.c index 4f226f5b..05c95274 100644 --- a/src/shell/container/start.c +++ b/src/shell/container/start.c @@ -12,7 +12,7 @@ static int usage(const char *argv0) return -1; } -int cmd_container_start(struct ocre_context *ctx, char *argv0, int argc, char **argv) +int cmd_container_start(struct ocre_context *ctx, const char *argv0, int argc, char **argv) { if (argc == 2) { struct ocre_container *container = ocre_context_get_container_by_id(ctx, argv[1]); diff --git a/src/shell/container/start.h b/src/shell/container/start.h index fb4c1392..b001d89e 100644 --- a/src/shell/container/start.h +++ b/src/shell/container/start.h @@ -1,3 +1,3 @@ #include -int cmd_container_start(struct ocre_context *ctx, char *argv0, int argc, char **argv); +int cmd_container_start(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/container/stop.c b/src/shell/container/stop.c index 1342850d..08c5e44f 100644 --- a/src/shell/container/stop.c +++ b/src/shell/container/stop.c @@ -12,7 +12,7 @@ static int usage(const char *argv0) return -1; } -int cmd_container_stop(struct ocre_context *ctx, char *argv0, int argc, char **argv) +int cmd_container_stop(struct ocre_context *ctx, const char *argv0, int argc, char **argv) { if (argc == 2) { struct ocre_container *container = ocre_context_get_container_by_id(ctx, argv[1]); diff --git a/src/shell/container/stop.h b/src/shell/container/stop.h index 5c0837e5..32ccc5c5 100644 --- a/src/shell/container/stop.h +++ b/src/shell/container/stop.h @@ -1,3 +1,3 @@ #include -int cmd_container_stop(struct ocre_context *ctx, char *argv0, int argc, char **argv); +int cmd_container_stop(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/container/unpause.c b/src/shell/container/unpause.c index 87a8919d..fc231085 100644 --- a/src/shell/container/unpause.c +++ b/src/shell/container/unpause.c @@ -12,7 +12,7 @@ static int usage(const char *argv0) return -1; } -int cmd_container_unpause(struct ocre_context *ctx, char *argv0, int argc, char **argv) +int cmd_container_unpause(struct ocre_context *ctx, const char *argv0, int argc, char **argv) { if (argc == 2) { struct ocre_container *container = ocre_context_get_container_by_id(ctx, argv[1]); diff --git a/src/shell/container/unpause.h b/src/shell/container/unpause.h index aadbf1f2..ba1346b4 100644 --- a/src/shell/container/unpause.h +++ b/src/shell/container/unpause.h @@ -1,3 +1,3 @@ #include -int cmd_container_unpause(struct ocre_context *ctx, char *argv0, int argc, char **argv); +int cmd_container_unpause(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/container/wait.c b/src/shell/container/wait.c index 1deb886b..f9886186 100644 --- a/src/shell/container/wait.c +++ b/src/shell/container/wait.c @@ -12,7 +12,7 @@ static int usage(const char *argv0) return -1; } -int cmd_container_wait(struct ocre_context *ctx, char *argv0, int argc, char **argv) +int cmd_container_wait(struct ocre_context *ctx, const char *argv0, int argc, char **argv) { if (argc == 2) { struct ocre_container *container = ocre_context_get_container_by_id(ctx, argv[1]); diff --git a/src/shell/container/wait.h b/src/shell/container/wait.h index dcd05370..3ca3ebb9 100644 --- a/src/shell/container/wait.h +++ b/src/shell/container/wait.h @@ -1,3 +1,3 @@ #include -int cmd_container_wait(struct ocre_context *ctx, char *argv0, int argc, char **argv); +int cmd_container_wait(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/image.c b/src/shell/image.c index 6e81da21..540dc1b9 100644 --- a/src/shell/image.c +++ b/src/shell/image.c @@ -7,7 +7,7 @@ #include "image/rm.h" #include "image/pull.h" -static int print_usage(struct ocre_context *ctx, char *argv0, int argc, char **argv) +static int print_usage(struct ocre_context *ctx, const char *argv0, int argc, char **argv) { fprintf(stderr, "Usage: %s image \n", argv0); @@ -25,7 +25,7 @@ static const struct ocre_command commands[] = { {"rm", cmd_image_rm}, }; -int cmd_image(struct ocre_context *ctx, char *argv0, int argc, char **argv) +int cmd_image(struct ocre_context *ctx, const char *argv0, int argc, char **argv) { if (argc < 2) { return print_usage(ctx, argv0, argc, argv); diff --git a/src/shell/image.h b/src/shell/image.h index 31c4ac49..efa4f924 100644 --- a/src/shell/image.h +++ b/src/shell/image.h @@ -1,3 +1,3 @@ #include -int cmd_image(struct ocre_context *ctx, char *argv0, int argc, char **argv); +int cmd_image(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/image/ls.c b/src/shell/image/ls.c index 6c4d662e..d100eba6 100644 --- a/src/shell/image/ls.c +++ b/src/shell/image/ls.c @@ -53,7 +53,7 @@ static int list_images(const char *path) { int ret = 0; DIR *d; - struct dirent *dir; + const struct dirent *dir; d = opendir(path); if (!d) { @@ -86,7 +86,7 @@ static int list_images(const char *path) return ret; } -int cmd_image_ls(struct ocre_context *ctx, char *argv0, int argc, char **argv) +int cmd_image_ls(struct ocre_context *ctx, const char *argv0, int argc, char **argv) { switch (argc) { case 1: { diff --git a/src/shell/image/ls.h b/src/shell/image/ls.h index a70b70ae..85562284 100644 --- a/src/shell/image/ls.h +++ b/src/shell/image/ls.h @@ -1,3 +1,3 @@ #include -int cmd_image_ls(struct ocre_context *ctx, char *argv0, int argc, char **argv); +int cmd_image_ls(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/image/pull.c b/src/shell/image/pull.c index ce48d6ed..f695700a 100644 --- a/src/shell/image/pull.c +++ b/src/shell/image/pull.c @@ -17,7 +17,7 @@ static int usage(const char *argv0) return -1; } -int cmd_image_pull(struct ocre_context *ctx, char *argv0, int argc, char **argv) +int cmd_image_pull(struct ocre_context *ctx, const char *argv0, int argc, char **argv) { char *local_name = NULL; int ret = -1; @@ -51,7 +51,7 @@ int cmd_image_pull(struct ocre_context *ctx, char *argv0, int argc, char **argv) /* Check if the provided image ID is valid */ - if (local_name && !ocre_is_valid_id(local_name)) { + if (!ocre_is_valid_id(local_name)) { fprintf(stderr, "Invalid characters in image ID '%s'. Valid are [a-z0-9_-.] (lowercase " "alphanumeric) and cannot start with '.'\n", diff --git a/src/shell/image/pull.h b/src/shell/image/pull.h index e5451a4d..85fe88f6 100644 --- a/src/shell/image/pull.h +++ b/src/shell/image/pull.h @@ -1,3 +1,3 @@ #include -int cmd_image_pull(struct ocre_context *ctx, char *argv0, int argc, char **argv); +int cmd_image_pull(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/image/rm.c b/src/shell/image/rm.c index 66e8a83d..3594bbac 100644 --- a/src/shell/image/rm.c +++ b/src/shell/image/rm.c @@ -13,7 +13,7 @@ static int usage(const char *argv0) return -1; } -int cmd_image_rm(struct ocre_context *ctx, char *argv0, int argc, char **argv) +int cmd_image_rm(struct ocre_context *ctx, const char *argv0, int argc, char **argv) { if (argc == 2) { /* Check if the provided image ID is valid */ diff --git a/src/shell/image/rm.h b/src/shell/image/rm.h index 5c61d6b6..4ac5d0f1 100644 --- a/src/shell/image/rm.h +++ b/src/shell/image/rm.h @@ -1,3 +1,3 @@ #include -int cmd_image_rm(struct ocre_context *ctx, char *argv0, int argc, char **argv); +int cmd_image_rm(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/shell.c b/src/shell/shell.c index 396e15e0..8105ce94 100644 --- a/src/shell/shell.c +++ b/src/shell/shell.c @@ -20,13 +20,13 @@ #include "container/wait.h" #include "container/create.h" -static int print_version(struct ocre_context *ctx, char *argv0, int argc, char **argv) +static int print_version(struct ocre_context *ctx, const char *argv0, int argc, char **argv) { fprintf(stdout, "Ocre version 1.0\n"); return 0; } -static int print_usage(struct ocre_context *ctx, char *argv0, int argc, char **argv) +static int print_usage(struct ocre_context *ctx, const char *argv0, int argc, char **argv) { fprintf(stderr, "Usage: %s [-v] \n", argv0); @@ -65,10 +65,10 @@ static const struct ocre_command commands[] = { {"create", cmd_container_create_run}, {"run", cmd_container_create_run}, {"start", cmd_container_start}, - // {"stop", cmd_container_stop}, + {"stop", cmd_container_stop}, {"kill", cmd_container_kill}, - // {"pause", cmd_container_pause}, - // {"unpause", cmd_container_unpause}, + {"pause", cmd_container_pause}, + {"unpause", cmd_container_unpause}, {"rm", cmd_container_rm}, /* image shortcuts */ {"images", cmd_image_ls}, From be670aff4f6585acad1b367467ce556bf7fa4bf2 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 13:12:48 +0100 Subject: [PATCH 162/234] chore(string_array): remove unused function Signed-off-by: Marco Casaroli --- src/ocre/util/string_array.c | 37 ------------------------------------ src/ocre/util/string_array.h | 10 ---------- 2 files changed, 47 deletions(-) diff --git a/src/ocre/util/string_array.c b/src/ocre/util/string_array.c index 224c1aa4..ef6168b9 100644 --- a/src/ocre/util/string_array.c +++ b/src/ocre/util/string_array.c @@ -19,29 +19,6 @@ size_t string_array_size(const char **array) return size; } -char **string_array_dup(char **src) -{ - size_t size = string_array_size((const char **)src); - - if (!size) { - return NULL; - } - - char **dst = malloc(size * sizeof(char *)); - if (!dst) { - return NULL; - } - - memset(dst, 0, size * sizeof(char *)); - - size_t i; - for (i = 0; i < size; i++) { - dst[i] = src[i]; - } - - return dst; -} - void string_array_free(char **array) { if (!array) { @@ -88,20 +65,6 @@ char **string_array_deep_dup(const char **const src) return NULL; } -size_t string_array_copy(char **dest, char **src) -{ - if (!dest || !src) { - return 0; - } - - size_t count = 0; - do { - dest[count] = src[count]; - } while (src[count]); - - return count; -} - const char *string_array_lookup(const char **array, const char *key) { if (!array || !key) { diff --git a/src/ocre/util/string_array.h b/src/ocre/util/string_array.h index 0ba946c4..d6126fbf 100644 --- a/src/ocre/util/string_array.h +++ b/src/ocre/util/string_array.h @@ -5,11 +5,6 @@ */ size_t string_array_size(const char **const array); -/* duplicates an array of char * - * returns NULL on error - */ -char **string_array_dup(char **src); - /* makes a deep copy of an array of char * * returns NULL on error */ @@ -20,11 +15,6 @@ char **string_array_deep_dup(const char **const src); */ void string_array_free(char **array); -/* copies an array of char * - * returns the number of elements copied - */ -size_t string_array_copy(char **dest, char **src); - /* looks up a key in an array of char * * returns NULL if not found */ From cf92be14b250576f4bc0449fd6222be68c0a0fa6 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 13:13:04 +0100 Subject: [PATCH 163/234] chore(memory): remove unused calloc function Signed-off-by: Marco Casaroli --- src/platform/include/ocre/platform/memory.h | 1 - src/platform/posix/memory.c | 5 ----- 2 files changed, 6 deletions(-) diff --git a/src/platform/include/ocre/platform/memory.h b/src/platform/include/ocre/platform/memory.h index b649d0a1..0202d4f9 100644 --- a/src/platform/include/ocre/platform/memory.h +++ b/src/platform/include/ocre/platform/memory.h @@ -2,5 +2,4 @@ void *user_malloc(size_t size); void user_free(void *p); -void *user_calloc(size_t n, size_t size); void *user_realloc(void *p, size_t size); diff --git a/src/platform/posix/memory.c b/src/platform/posix/memory.c index d3be68a5..6135fb7d 100644 --- a/src/platform/posix/memory.c +++ b/src/platform/posix/memory.c @@ -11,11 +11,6 @@ void user_free(void *p) free(p); } -void *user_calloc(size_t n, size_t size) -{ - return calloc(n, size); -} - void *user_realloc(void *p, size_t size) { return realloc(p, size); From e7a925452f8144924c17fd60741e46aac931875f Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 13:14:02 +0100 Subject: [PATCH 164/234] fix(ocre_api): output formatting The proper way of handling printf of uint32_t is using the inttypes.h macros. Signed-off-by: Marco Casaroli --- src/runtime/wamr/ocre_api/ocre_common.c | 13 +++++++------ .../wamr/ocre_api/ocre_messaging/ocre_messaging.c | 14 ++++++++------ src/runtime/wamr/ocre_api/ocre_timers/ocre_timer.c | 12 +++++++----- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/runtime/wamr/ocre_api/ocre_common.c b/src/runtime/wamr/ocre_api/ocre_common.c index b527242c..f2032345 100644 --- a/src/runtime/wamr/ocre_api/ocre_common.c +++ b/src/runtime/wamr/ocre_api/ocre_common.c @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -149,9 +150,9 @@ int ocre_get_event(wasm_exec_env_t exec_env, uint32_t type_offset, uint32_t id_o break; } case OCRE_RESOURCE_TYPE_MESSAGING: { - LOG_DBG("Retrieved Messaging event: message_id=%u, topic=%s, " - "topic_offset=%u, content_type=%s, " - "content_type_offset=%u, payload_len=%d, owner=%p", + LOG_DBG("Retrieved Messaging event: message_id=%" PRIu32 ", topic=%s, " + "topic_offset=%" PRIu32 ", content_type=%s, " + "content_type_offset=%" PRIu32 ", payload_len=%" PRIu32 ", owner=%p", event.data.messaging_event.message_id, event.data.messaging_event.topic, event.data.messaging_event.topic_offset, event.data.messaging_event.content_type, event.data.messaging_event.content_type_offset, event.data.messaging_event.payload_len, @@ -171,7 +172,7 @@ int ocre_get_event(wasm_exec_env_t exec_env, uint32_t type_offset, uint32_t id_o */ default: { core_spinlock_unlock(&ocre_event_queue_lock, key); - LOG_ERR("Invalid event type: %u", event.type); + LOG_ERR("Invalid event type: %" PRIu32, event.type); return -EINVAL; } } @@ -354,7 +355,7 @@ void ocre_increment_resource_count(wasm_module_inst_t module_inst, ocre_resource core_mutex_lock(®istry_mutex); ctx->resource_count[type]++; core_mutex_unlock(®istry_mutex); - LOG_INF("Incremented resource count: type=%d, count=%d", type, ctx->resource_count[type]); + LOG_INF("Incremented resource count: type=%d, count=%" PRIu32, type, ctx->resource_count[type]); } } @@ -365,7 +366,7 @@ void ocre_decrement_resource_count(wasm_module_inst_t module_inst, ocre_resource core_mutex_lock(®istry_mutex); ctx->resource_count[type]--; core_mutex_unlock(®istry_mutex); - LOG_INF("Decremented resource count: type=%d, count=%d", type, ctx->resource_count[type]); + LOG_INF("Decremented resource count: type=%d, count=%" PRIu32, type, ctx->resource_count[type]); } } diff --git a/src/runtime/wamr/ocre_api/ocre_messaging/ocre_messaging.c b/src/runtime/wamr/ocre_api/ocre_messaging/ocre_messaging.c index 61f3c096..42f74810 100644 --- a/src/runtime/wamr/ocre_api/ocre_messaging/ocre_messaging.c +++ b/src/runtime/wamr/ocre_api/ocre_messaging/ocre_messaging.c @@ -6,6 +6,7 @@ */ #include +#include #include @@ -102,7 +103,7 @@ int ocre_messaging_subscribe(wasm_exec_env_t exec_env, void *topic) return -EINVAL; } - ocre_module_context_t *ctx = ocre_get_module_context(module_inst); + const ocre_module_context_t *ctx = ocre_get_module_context(module_inst); if (!ctx) { LOG_ERR("Module context not found for module instance %p", (void *)module_inst); return -EINVAL; @@ -233,18 +234,19 @@ int ocre_messaging_publish(wasm_exec_env_t exec_env, void *topic, void *content_ event.data.messaging_event.payload_len = (uint32_t)payload_len; event.owner = target_module; - LOG_DBG("Creating messaging event: ID=%d, topic=%s, content_type=%s, payload_len=%d for module %p", + LOG_DBG("Creating messaging event: ID=%" PRIu32 + ", topic=%s, content_type=%s, payload_len=%d for module %p", message_id, (char *)topic, (char *)content_type, payload_len, (void *)target_module); core_spinlock_key_t key = core_spinlock_lock(&ocre_event_queue_lock); if (core_eventq_put(&ocre_event_queue, &event) != 0) { - LOG_ERR("Failed to queue messaging event for message ID %d", message_id); + LOG_ERR("Failed to queue messaging event for message ID %" PRIu32, message_id); wasm_runtime_module_free(target_module, topic_offset); wasm_runtime_module_free(target_module, content_offset); wasm_runtime_module_free(target_module, payload_offset); } else { message_sent = true; - LOG_DBG("Queued messaging event for message ID %d", message_id); + LOG_DBG("Queued messaging event for message ID %" PRIu32, message_id); } core_spinlock_unlock(&ocre_event_queue_lock, key); } @@ -252,8 +254,8 @@ int ocre_messaging_publish(wasm_exec_env_t exec_env, void *topic, void *content_ core_mutex_unlock(&messaging_system.mutex); if (message_sent) { - LOG_DBG("Published message: ID=%d, topic=%s, content_type=%s, payload_len=%d", message_id, - (char *)topic, (char *)content_type, payload_len); + LOG_DBG("Published message: ID=%" PRIu32 ", topic=%s, content_type=%s, payload_len=%" PRIu32 "", + message_id, (char *)topic, (char *)content_type, payload_len); message_id++; return 0; } else { diff --git a/src/runtime/wamr/ocre_api/ocre_timers/ocre_timer.c b/src/runtime/wamr/ocre_api/ocre_timers/ocre_timer.c index 35e68ff7..53d3dd05 100644 --- a/src/runtime/wamr/ocre_api/ocre_timers/ocre_timer.c +++ b/src/runtime/wamr/ocre_api/ocre_timers/ocre_timer.c @@ -10,6 +10,7 @@ #include #include #include +#include #include @@ -180,7 +181,7 @@ int ocre_timer_get_remaining(wasm_exec_env_t exec_env, ocre_timer_t id) return -EINVAL; } - ocre_timer_internal *timer = &timers[id - 1]; + const ocre_timer_internal *timer = &timers[id - 1]; if (!timer->in_use || timer->owner != module) { LOG_ERR("Timer ID %d not in use or not owned by module %p", id, (void *)module); return -EINVAL; @@ -242,7 +243,7 @@ static void unified_timer_callback(void *user_data) return; } - LOG_DBG("Timer callback for timer %d", timer->id); + LOG_DBG("Timer callback for timer %" PRIu32, timer->id); // For non-periodic timers, mark as not running if (!timer->periodic) { @@ -258,13 +259,14 @@ static void unified_timer_callback(void *user_data) event.data.timer_event.timer_id = timer->id; event.owner = timer->owner; - LOG_DBG("Creating timer event: type=%d, id=%d, for owner %p", event.type, timer->id, (void *)timer->owner); + LOG_DBG("Creating timer event: type=%d, id=%" PRIu32 ", for owner %p", event.type, timer->id, + (void *)timer->owner); core_spinlock_key_t key = core_spinlock_lock(&ocre_event_queue_lock); if (core_eventq_put(&ocre_event_queue, &event) != 0) { - LOG_ERR("Failed to queue timer event for timer %d", timer->id); + LOG_ERR("Failed to queue timer event for timer %" PRIu32, timer->id); } else { - LOG_DBG("Queued timer event for timer %d", timer->id); + LOG_DBG("Queued timer event for timer %" PRIu32, timer->id); } core_spinlock_unlock(&ocre_event_queue_lock, key); } From bcbbed7e362192a45f149b4f02d7e11a1c9163d9 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 13:17:00 +0100 Subject: [PATCH 165/234] chore(sha256): remove unused functions Signed-off-by: Marco Casaroli --- src/shell/sha256/sha256.c | 16 ---------------- src/shell/sha256/sha256.h | 6 ------ 2 files changed, 22 deletions(-) diff --git a/src/shell/sha256/sha256.c b/src/shell/sha256/sha256.c index f3fcec33..d44443be 100644 --- a/src/shell/sha256/sha256.c +++ b/src/shell/sha256/sha256.c @@ -173,19 +173,3 @@ void sha256_read_hex(const struct sha256_buff *buff, char *hex) sha256_read(buff, hash); bin_to_hex(hash, 32, hex); } - -void sha256_easy_hash(const void *data, size_t size, uint8_t *hash) -{ - struct sha256_buff buff; - sha256_init(&buff); - sha256_update(&buff, data, size); - sha256_finalize(&buff); - sha256_read(&buff, hash); -} - -void sha256_easy_hash_hex(const void *data, size_t size, char *hex) -{ - uint8_t hash[32]; - sha256_easy_hash(data, size, hash); - bin_to_hex(hash, 32, hex); -} diff --git a/src/shell/sha256/sha256.h b/src/shell/sha256/sha256.h index a64b6d7c..efc784c5 100644 --- a/src/shell/sha256/sha256.h +++ b/src/shell/sha256/sha256.h @@ -52,10 +52,4 @@ void sha256_read(const struct sha256_buff *buff, uint8_t *hash); /* Read digest into 64-char string as hex (without null-byte) */ void sha256_read_hex(const struct sha256_buff *buff, char *hex); -/* Hashes single contiguous block of data and reads digest into 32-byte binary array */ -void sha256_easy_hash(const void *data, size_t size, uint8_t *hash); - -/* Hashes single contiguous block of data and reads digest into 64-char string (without null-byte) */ -void sha256_easy_hash_hex(const void *data, size_t size, char *hex); - #endif From 58492af07e71a8b6b5ade5ba0868ba838993a171 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 13:17:57 +0100 Subject: [PATCH 166/234] fix(shell/pull): remove useless check This is already checked below. Signed-off-by: Marco Casaroli --- src/shell/image/pull.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/shell/image/pull.c b/src/shell/image/pull.c index f695700a..d7f26979 100644 --- a/src/shell/image/pull.c +++ b/src/shell/image/pull.c @@ -42,11 +42,6 @@ int cmd_image_pull(struct ocre_context *ctx, const char *argv0, int argc, char * } else { local_name = argv[2]; - - if (strchr(local_name, '/')) { - fprintf(stderr, "Local file '%s' cannot contain '/'\n", argv[2]); - return -1; - } } /* Check if the provided image ID is valid */ From 5dfe6f8babfc432bca06e13db5ce8825b619b34f Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 13:18:23 +0100 Subject: [PATCH 167/234] fix(ocre_api): remove unnecessary check This function always succeeds. Signed-off-by: Marco Casaroli --- .../wamr/ocre_api/ocre_messaging/ocre_messaging.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/runtime/wamr/ocre_api/ocre_messaging/ocre_messaging.c b/src/runtime/wamr/ocre_api/ocre_messaging/ocre_messaging.c index 42f74810..791fc271 100644 --- a/src/runtime/wamr/ocre_api/ocre_messaging/ocre_messaging.c +++ b/src/runtime/wamr/ocre_api/ocre_messaging/ocre_messaging.c @@ -86,10 +86,7 @@ void ocre_messaging_cleanup_container(wasm_module_inst_t module_inst) int ocre_messaging_subscribe(wasm_exec_env_t exec_env, void *topic) { if (!messaging_system_initialized) { - if (ocre_messaging_init() != 0) { - LOG_ERR("Failed to initialize messaging system"); - return -EINVAL; - } + ocre_messaging_init(); } if (!topic || ((char *)topic)[0] == '\0') { @@ -147,10 +144,7 @@ int ocre_messaging_subscribe(wasm_exec_env_t exec_env, void *topic) int ocre_messaging_publish(wasm_exec_env_t exec_env, void *topic, void *content_type, void *payload, int payload_len) { if (!messaging_system_initialized) { - if (ocre_messaging_init() != 0) { - LOG_ERR("Failed to initialize messaging system"); - return -EINVAL; - } + ocre_messaging_init(); } if (!topic || ((char *)topic)[0] == '\0') { From 01133c64c5a2d78e700d697d0b7e8c9f62e08b20 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 13:22:47 +0100 Subject: [PATCH 168/234] feat(samples): add posix static_check demo This does not do anything, but links with the shell. It will be used for cppcheck. Signed-off-by: Marco Casaroli --- CMakeLists.txt | 6 ++++ .../static_checks/posix/CMakeLists.txt | 23 +++++++++++++ .../static_checks/posix/download_file.c | 6 ++++ src/samples/static_checks/posix/ocre.c | 33 +++++++++++++++++++ 4 files changed, 68 insertions(+) create mode 100644 src/samples/static_checks/posix/CMakeLists.txt create mode 100644 src/samples/static_checks/posix/download_file.c create mode 100644 src/samples/static_checks/posix/ocre.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 75324e4f..6f8a4b95 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,12 @@ add_subdirectory(src/runtime/wamr) # platform add_subdirectory(src/platform/posix) +# platform +add_subdirectory(src/shell) + # samples add_subdirectory(src/samples/mini/posix) add_subdirectory(src/samples/demo/posix) + +# this sample is useful only for static code analysis on POSIX +add_subdirectory(src/samples/static_checks/posix) diff --git a/src/samples/static_checks/posix/CMakeLists.txt b/src/samples/static_checks/posix/CMakeLists.txt new file mode 100644 index 00000000..5c1797f1 --- /dev/null +++ b/src/samples/static_checks/posix/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.20.0) + +project (ocre_cmd) + +add_executable(ocre_cmd + ocre.c + download_file.c +) + +target_link_libraries(ocre_cmd + PUBLIC + OcreCore + OcreShell +) + +target_link_libraries(OcreShell + PUBLIC + OcreCore +) + +set(THREADS_PREFER_PTHREAD_FLAG TRUE) +find_package(Threads) +target_link_libraries(ocre_cmd PRIVATE Threads::Threads) diff --git a/src/samples/static_checks/posix/download_file.c b/src/samples/static_checks/posix/download_file.c new file mode 100644 index 00000000..28b379f9 --- /dev/null +++ b/src/samples/static_checks/posix/download_file.c @@ -0,0 +1,6 @@ +int ocre_download_file(const char *url, const char *filepath) +{ + /* Not implemented */ + + return -1; +} diff --git a/src/samples/static_checks/posix/ocre.c b/src/samples/static_checks/posix/ocre.c new file mode 100644 index 00000000..ad4f4595 --- /dev/null +++ b/src/samples/static_checks/posix/ocre.c @@ -0,0 +1,33 @@ +#include +#include +#include + +#include + +/* keep a reference to the single instance of the runtime */ + +struct ocre_context *ocre_global_context = NULL; + +int main(int argc, char *argv[]) +{ + /* Initialize Ocre */ + + if (ocre_initialize(NULL)) { + return -1; + } + + fprintf(stderr, "Initialized Ocre\n"); + + /* Create a context */ + + ocre_global_context = ocre_create_context(NULL); + if (!ocre_global_context) { + fprintf(stderr, "Failed to create Ocre context\n"); + ocre_deinitialize(); + return -1; + } + + fprintf(stderr, "Created Ocre context: %p\n", ocre_global_context); + + return ocre_shell(ocre_global_context, argc, argv); +} From 394e1bde8977a7e3dcb2804bb6925bf4400dc50e Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 14:54:30 +0100 Subject: [PATCH 169/234] doc(README): update Add the new instructions for Linux and Zephyr. Signed-off-by: Marco Casaroli --- README.md | 262 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 148 insertions(+), 114 deletions(-) diff --git a/README.md b/README.md index 5c256690..084a01eb 100644 --- a/README.md +++ b/README.md @@ -20,194 +20,227 @@ Our mission is to make it as easy to develop and securely deploy apps for the bi Ocre supports a range of features depending on the platform. The table below summarizes the current support: -| Feature | Zephyr (native_sim, b_u585i_iot02a) | Linux | -|------------------------|:-----------------------------------:|:-------------:| -| Ocre Runtime | ✅ | ✅ | -| Container Messaging | ✅ | ✅ | -| GPIO | ✅ | ❌ | -| Timers | ✅ | ✅ | -| Sensors | ✅ | ❌ | -| Networking | ✅ | ✅ | -| Filesystem | ✅ | ✅ | -| Interactive Shell | ✅ | ❌ | +| Feature | Zephyr (native_sim, b_u585i_iot02a) | Linux | +| ------------------- | :---------------------------------: | :---: | +| Ocre Runtime | ✅ | ✅ | +| Container Messaging | ✅ | ✅ | +| GPIO | ✅ | ❌ | +| Timers | ✅ | ✅ | +| Sensors | ✅ | ❌ | +| Networking | ✅ | ✅ | +| Filesystem | ✅ | ✅ | +| Interactive Shell | ✅ | ❌ | - **Zephyr**: Full feature set, including hardware integration and shell. - **Linux**: Core runtime and multiple I/O features; hardware and shell features are not available. --- -## Getting Started +# Getting Started -This guide will help you build and run Ocre on both Zephyr (simulated and hardware) and Linux. +## Zephyr -### Prerequisites +### Devcontainer -- **Zephyr SDK** (for Zephyr targets) -- **Python 3** (for build tooling) -- **CMake** and **make** (for Linux builds) -- **west** (Zephyr meta-tool) -- **git** +We provide an optional devcontainer for building Zephyr with Ocre. However, we suggest Zephyr development to be done in the host outside docker, because it will be easier to flash and debug the board, the devcontainer is provided as a quick and handy way of reproducing the environment we have in the CI. ---- +### Zephyr Integration -### Setup +Ocre is a collection of a External Zephyr module, a few sample applications and a an optional slim West project for building for a small set of platforms. -#### Zephyr +More boards are supported in Ocre with a full West Project, however, our optional West project can be used to get started fast and in our CI. -Follow the [Zephyr Getting Started Guide](https://docs.zephyrproject.org/3.7.0/develop/getting_started/index.html) for your OS, including: -- [Install dependencies](https://docs.zephyrproject.org/3.7.0/develop/getting_started/index.html#install-dependencies) -- [Install the Zephyr SDK](https://docs.zephyrproject.org/3.7.0/develop/getting_started/index.html#install-the-zephyr-sdk) +### Quick Zephyr build with our West project -#### Python Virtual Environment (Recommended) +This will very quickly build the images for one of the officially supported boards. Open a terminal in Ubuntu 22.04 or newer and run: + +Install Ubuntu dependencies: ```sh -mkdir runtime && cd runtime -python3 -m venv .venv -source .venv/bin/activate +sudo apt update +sudo apt upgrade +sudo apt install --no-install-recommends git cmake ninja-build gperf \ + ccache dfu-util device-tree-compiler wget python3-dev python3-venv python3-tk \ + xz-utils file make gcc gcc-multilib g++-multilib libsdl2-dev libmagic1 curl ``` -You may need to install `python3-venv` on your system. - -#### Install West -Install the [west](https://docs.zephyrproject.org/latest/develop/west/index.html) CLI tool, which is needed to build, run and manage Zephyr applications. +Install [WASI-SDK](https://github.com/WebAssembly/wasi-sdk/releases): ```sh -pip install west +mkdir /opt/wasi-sdk && \ + curl -sSL https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-29/wasi-sdk-29.0-$(uname -m | sed s/aarch64/arm64/)-linux.tar.gz | \ + sudo tar zxvf - --strip-components=1 -C /opt/wasi-sdk ``` -#### Initialize and Update Zephyr Workspace +Create Zephyr project directory, venv and install python dependencies: ```sh -west init -m git@github.com:project-ocre/ocre-runtime.git -west update +mkdir ~/zephyrproject +python3 -m venv ~/zephyrproject/.venv +source ~/zephyrproject/.venv/bin/activate +pip install littlefs-python ``` -#### Install Zephyr Python Requirements +Zephyr workspace initialization: ```sh -pip install -r zephyr/scripts/requirements.txt +cd ~/zephyrproject +west init -m https://github.com/ocre-project/ocre.git +west update +west zephyr-export ``` ---- +Install SDK and Python packages: -#### Linux +```sh +west packages pip --install +west sdk install -t \ + x86_64-zephyr-elf \ + aarch64-zephyr-elf \ + arm-zephyr-eabi +``` -#### Clone the Repository +Build the sample application: ```sh -git clone git@github.com:project-ocre/ocre-runtime.git -cd ocre-runtime +west build -p always -b b_u585i_iot02a ocre-runtime/src/samples/demo/zephyr ``` -#### Initialize submodules +Connect the board and flash the application: + ```sh -git submodule update --init --recursive +west flash ``` -## Building and Running +Alternatively, you can try the `mini` or `supervisor` samples. -### Using the `build.sh` Script (Recommended) +### Full Zephyr build from scratch -Ocre provides a convenient `build.sh` script to simplify building and running for both Zephyr and Linux targets. +These instructions work natively for Linux, MacOS and WSL2. If this is used in docker, it might require some special configuration for being able to flash or debug the board. -#### Usage +1. Follow the instructions on the [Zephyr Getting Started Guide](https://docs.zephyrproject.org/latest/develop/getting_started/index.html) for your OS, until you can build a sample application from Zephyr. -```sh -./build.sh -t [-r] [-f [file2 ...]] [-b] [-h] -``` +2. Install `littlefs-python`: -- `-t `: **Required**. `z` for Zephyr, `l` for Linux. -- `-r`: Run after build (optional). -- `-f `: Specify one or more input files (optional). -- `-b `: (Zephyr only) Select a zephyr board instead of the default `native_sim`: - - `uw` -> b_u585i_iot02a + W5500 - - `ue` -> b_u585i_iot02a + ENC28J60 - - `your_option` -> any Zephyr-supported board -- `-h`: Show help. + ```sh + pip install littlefs-python + ``` -#### Examples +3. Install [WASI-SDK](https://github.com/WebAssembly/wasi-sdk/releases) -**Build and run for Zephyr native_sim:** -```sh -./build.sh -t z -r -``` +WASI-SDK is expected to be installed in `/opt/wasi-sdk`. -**Build for Zephyr b_u585i_iot02a board:** -```sh -./build.sh -t z -b -``` +Check-out the ocre-runtime repository alongside the zephyr repositories or anywhere and just build one of our sample applications like: -**Build and run for Linux with a WASM file:** ```sh -./build.sh -t l -r -f your_file.wasm +west build -p always -b ocre-runtime/src/samples//zephyr ``` ---- - -### Manual Build Steps +See below for the available applications and officially supported boards. -#### Zephyr (native_sim) +You can also change the Kconfig options for Zephyr and ocre with: ```sh -west build -b native_sim ./application -d build -- -DMODULE_EXT_ROOT=`pwd`/application -./build/zephyr/zephyr.exe +west build -t menuconfig ``` -#### Zephyr (b_u585i_iot02a) +Followed by: ```sh -west build -b b_u585i_iot02a ./application -d build -- -DMODULE_EXT_ROOT=`pwd`/application -# Flash to board (requires hardware) +west build west flash ``` -#### Linux x86_64 +### Quick Zephyr build with devcontainer + +This will very quickly build the images for one of the officially supported boards. The devcontainer already includes the Zephyr SDK, WASI-SDK the Python venv and all the necessary tools. + +Build and open the 'zephyr' devcontainer of this repository. + +Open a terminal in the devcontainer and run: ```sh -mkdir -p build -cd build -cmake .. -DTARGET_PLATFORM_NAME=Linux -make -./app your_file.wasm +west init . +west update +west build -p always -b ocre-runtime/src/samples//zephyr ``` ---- +The build artifacts are in the `build/zephyr` directory. You might need to set-up some docker mounts and permissions for flashing the board. + +See below for the available applications and officially supported boards. + +### Official boards and sample applications + +The officially supported boards are listed below: + +| Board | Name | +| ------------------------ | ----------------------------------------------------------------------------------------------- | +| `native_sim` | 32-bit native simulator | +| `native_sim/native/64` | 64-bit native simulator | +| `pico_plus2/rp2350b/m33` | Pimoroni Pico Plus 2 | +| `b_u585i_iot02a` | [B-U585I-IOT02A](https://docs.zephyrproject.org/latest/boards/st/b_u585i_iot02a/doc/index.html) | + +Other boards might work. Check the [Zephyr documentation](https://docs.zephyrproject.org/latest/boards/index.html) for a list of supported boards in Zephyr. + +The officially supported sample applications are listed below: + +| Sample | Description | +| ------------ | ---------------------------------------------------------- | +| `mini` | A simple "Hello World" application using minimal resources | +| `demo` | A more featured sample application | +| `supervisor` | Interactive shell control | + +The intended usage of the samples are: + +- Use the `mini` sample to see how Ocre can work on your board. +- Use the `demo` sample to test some more Ocre features. +- Use the `supervisor` sample to have full interactive control from the shell command line. + +## Linux -## Additional Notes +### Devcontainer -- The `build.sh` script will automatically detect the target and handle build/run steps, including passing input files and selecting the correct Zephyr board. -- For Zephyr, only the first file specified with `-f` is passed as the input file (see script for details). -- For Linux, you can pass multiple WASM files as arguments to the built application. -- The script checks build success and only runs the application if the build completes successfully. -- The `mini-samples` directory contains a "Hello World" container, which is hardcoded as a C array. When Ocre is run without input file arguments, it executes this sample container by default. If an input file is provided, Zephyr will convert that file into a C array at build time and run it as a container. On Linux, this conversion does not occur — instead, Ocre simply opens and reads the provided file(s) directly from the filesystem. +We also provide a devcontainer for Linux. This is the recommended way to get started with Ocre on Linux. However these instructions will work for native Linux builds. -## Sample Output +### Prerequisites + +- Ubuntu 22.04 or later +- CMake > 3.20 +- git > 2.28 +- A working C compiler (gcc or clang) +- [WASI-SDK](https://github.com/WebAssembly/wasi-sdk/releases) installed under `/opt/wasi-sdk` + +Other Linux distributions might work, but are not actively tested. + +You can get this easily on a new Ubuntu by running: -#### Zephyr (b_u585i_iot02a) ```sh -./build.sh -t z -r -b ue +sudo apt update +sudo apt install -y cmake git build-essential ``` -##### Output +Or you can use the devcontainer, which already has everything preinstalled. + +Clone the repository and the submodules: + ```sh -Target is: Zephyr -Building for b_u585i_iot02a with ENC28J60 support -Linking C executable zephyr/zephyr.elf -Ocre runtime started -Hello World from Ocre! +git clone https://github.com/project-ocre/ocre-runtime.git +cd ocre-runtime +git submodule update --init --recursive ``` -#### Linux +Run the CMake build, like: + ```sh -./build.sh -t l -r +mkdir build && cd build +cmake .. +make ``` -##### Output +The relevant binaries are stored in `build/src/samples/mini/posix` and `build/src/samples/demo/posix`. You can run them directly: + ```sh -Target is: Linux -[100%] Built target app -Ocre runtime started -Hello World from Ocre! +./build/src/samples/mini/posix/mini ``` ## License @@ -217,8 +250,9 @@ Distributed under the Apache License 2.0. See [LICENSE](https://github.com/proje --- ## More Info -* **[Website](https://lfedge.org/projects/ocre/)**: For a high-level overview of the Ocre project, and its goals, visit our website. -* **[Docs](https://docs.project-ocre.org/)**: For more detailed information about the Ocre runtime, visit Ocre docs. -* **[Wiki](https://lf-edge.atlassian.net/wiki/spaces/OCRE/overview?homepageId=14909442)**: For a full project overview, FAQs, project roadmap, and governance information, visit the Ocre Wiki. -* **[Slack](https://lfedge.slack.com/archives/C07F190CC3X)**: If you need support or simply want to discuss all things Ocre, head on over to our Slack channel (`#ocre`) on LFEdge's Slack org. -* **[Mailing list](https://lists.lfedge.org/g/Ocre-TSC)**: Join the Ocre Technical Steering Committee (TSC) mailing list to stay up to date with important project announcements, discussions, and meetings. + +- **[Website](https://lfedge.org/projects/ocre/)**: For a high-level overview of the Ocre project, and its goals, visit our website. +- **[Docs](https://docs.project-ocre.org/)**: For more detailed information about the Ocre runtime, visit Ocre docs. +- **[Wiki](https://lf-edge.atlassian.net/wiki/spaces/OCRE/overview?homepageId=14909442)**: For a full project overview, FAQs, project roadmap, and governance information, visit the Ocre Wiki. +- **[Slack](https://lfedge.slack.com/archives/C07F190CC3X)**: If you need support or simply want to discuss all things Ocre, head on over to our Slack channel (`#ocre`) on LFEdge's Slack org. +- **[Mailing list](https://lists.lfedge.org/g/Ocre-TSC)**: Join the Ocre Technical Steering Committee (TSC) mailing list to stay up to date with important project announcements, discussions, and meetings. From 81504dd5c04b4a1bc27a117dc1e0d77a01a1131a Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 19:19:49 +0100 Subject: [PATCH 170/234] fix(container): return error code if failed on EXITED Return an error code if the container fails to join Signed-off-by: Marco Casaroli --- src/ocre/container.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ocre/container.c b/src/ocre/container.c index 187ad476..01b7222c 100644 --- a/src/ocre/container.c +++ b/src/ocre/container.c @@ -612,8 +612,6 @@ int ocre_container_wait(struct ocre_container *container, int *status) } } - ret = 0; - if (container->status == OCRE_CONTAINER_STATUS_EXITED) { LOG_INF("Container '%s' was exited", container->id); if (ocre_container_status_locked(container) != OCRE_CONTAINER_STATUS_STOPPED) { @@ -622,9 +620,10 @@ int ocre_container_wait(struct ocre_container *container, int *status) } } + ret = 0; + if (container->status == OCRE_CONTAINER_STATUS_STOPPED) { LOG_INF("Container '%s' was stopped", container->id); - ret = 0; if (status) { *status = container->exit_code; } From 1e0964e4b296999dd3071742e64402501b0fdbc1 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 19:22:04 +0100 Subject: [PATCH 171/234] fix(context): handle invalid id correctly And the freeing of the mutex. We must still return rc. So we must not override it. Signed-off-by: Marco Casaroli --- src/ocre/context.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/ocre/context.c b/src/ocre/context.c index f0f1179e..6f76041d 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -182,7 +182,6 @@ struct ocre_context *ocre_create_context(const char *workdir) context->working_directory = strdup(workdir); if (!context->working_directory) { LOG_ERR("Failed to allocate memory for working directory: errno=%d", errno); - free(context); goto error; } @@ -302,7 +301,7 @@ struct ocre_container *ocre_context_create_container(struct ocre_context *contex /* Check if the provided image ID is valid */ - if (image && !ocre_is_valid_id(image)) { + if (!image || !ocre_is_valid_id(image)) { LOG_ERR("Invalid characters in image ID '%s'. Valid are [a-z0-9_-.] (lowercase alphanumeric) and " "cannot start with '.'", image); @@ -472,13 +471,13 @@ int ocre_context_remove_container(struct ocre_context *context, struct ocre_cont } } -finish: - rc = pthread_mutex_unlock(&context->mutex); - if (rc) { +finish: { + int ret = pthread_mutex_unlock(&context->mutex); + if (ret) { LOG_ERR("Failed to unlock context mutex: rc=%d", rc); return -1; } - +} return rc; } From 1562a0fe11ee181e72ca98181a2fef2be4670d6b Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 19:22:59 +0100 Subject: [PATCH 172/234] chore(shell): add cppcheck suppression cppcheck is complaining that the context pointer could be const. We do not want these files to take const, because they would be unusable in the structure that can have the other files that do not take const context pointer. Signed-off-by: Marco Casaroli --- src/shell/image/ls.c | 1 + src/shell/image/pull.c | 1 + src/shell/image/rm.c | 1 + 3 files changed, 3 insertions(+) diff --git a/src/shell/image/ls.c b/src/shell/image/ls.c index d100eba6..fd76a94c 100644 --- a/src/shell/image/ls.c +++ b/src/shell/image/ls.c @@ -86,6 +86,7 @@ static int list_images(const char *path) return ret; } +/* cppcheck-suppress constParameterPointer */ int cmd_image_ls(struct ocre_context *ctx, const char *argv0, int argc, char **argv) { switch (argc) { diff --git a/src/shell/image/pull.c b/src/shell/image/pull.c index d7f26979..3eb780b1 100644 --- a/src/shell/image/pull.c +++ b/src/shell/image/pull.c @@ -17,6 +17,7 @@ static int usage(const char *argv0) return -1; } +/* cppcheck-suppress constParameterPointer */ int cmd_image_pull(struct ocre_context *ctx, const char *argv0, int argc, char **argv) { char *local_name = NULL; diff --git a/src/shell/image/rm.c b/src/shell/image/rm.c index 3594bbac..865ba8ad 100644 --- a/src/shell/image/rm.c +++ b/src/shell/image/rm.c @@ -13,6 +13,7 @@ static int usage(const char *argv0) return -1; } +/* cppcheck-suppress constParameterPointer */ int cmd_image_rm(struct ocre_context *ctx, const char *argv0, int argc, char **argv) { if (argc == 2) { From 177cc2ddb2c373ccee759aab75a2ef877ab74eee Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 19:25:30 +0100 Subject: [PATCH 173/234] chore(rm_rf): remove AI comment The AI is friend. Signed-off-by: Marco Casaroli --- src/ocre/util/rm_rf.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/ocre/util/rm_rf.c b/src/ocre/util/rm_rf.c index a40b3031..53045a77 100644 --- a/src/ocre/util/rm_rf.c +++ b/src/ocre/util/rm_rf.c @@ -6,8 +6,6 @@ #include #include -/* AI generated code: please don't joke */ - /* Stack node for directory traversal */ struct dir_stack_node { From 4d634ce0d4ac5424e4f2310b46f126fa84fa8615 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 19:29:37 +0100 Subject: [PATCH 174/234] chore: move unique_random_id to util Signed-off-by: Marco Casaroli --- src/ocre/CMakeLists.txt | 4 ++-- src/ocre/context.c | 2 +- src/ocre/{ => util}/unique_random_id.c | 2 +- src/ocre/{ => util}/unique_random_id.h | 0 4 files changed, 4 insertions(+), 4 deletions(-) rename src/ocre/{ => util}/unique_random_id.c (97%) rename src/ocre/{ => util}/unique_random_id.h (100%) diff --git a/src/ocre/CMakeLists.txt b/src/ocre/CMakeLists.txt index dddbdd89..67776081 100644 --- a/src/ocre/CMakeLists.txt +++ b/src/ocre/CMakeLists.txt @@ -45,10 +45,10 @@ target_sources(OcreCore PRIVATE container.c context.c - unique_random_id.c ocre.c - util/string_array.c util/rm_rf.c + util/string_array.c + util/unique_random_id.c commit_id.h include/ocre/build_info.h ) diff --git a/src/ocre/context.c b/src/ocre/context.c index 6f76041d..d3862156 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -13,9 +13,9 @@ #include #include "container.h" -#include "unique_random_id.h" #include "util/rm_rf.h" #include "util/string_array.h" +#include "util/unique_random_id.h" #define RANDOM_ID_LEN 8 diff --git a/src/ocre/unique_random_id.c b/src/ocre/util/unique_random_id.c similarity index 97% rename from src/ocre/unique_random_id.c rename to src/ocre/util/unique_random_id.c index 1d8dc10d..2fd4eaa8 100644 --- a/src/ocre/unique_random_id.c +++ b/src/ocre/util/unique_random_id.c @@ -2,7 +2,7 @@ #include #include -#include "context.h" +#include "../context.h" #include "unique_random_id.h" diff --git a/src/ocre/unique_random_id.h b/src/ocre/util/unique_random_id.h similarity index 100% rename from src/ocre/unique_random_id.h rename to src/ocre/util/unique_random_id.h From b70ab831454a7d011f9cfd8faf5f03150fccb2e9 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 19:49:57 +0100 Subject: [PATCH 175/234] chore: move fstab overlay to its own file Remove the repetition from each device and add as a extra overlay file for the application. Signed-off-by: Marco Casaroli --- src/samples/demo/zephyr/CMakeLists.txt | 3 +++ .../demo/zephyr/boards/native_sim_64.overlay | 17 ----------------- .../boards/pico_plus2_rp2350b_m33.overlay | 17 ----------------- .../boards/pico_plus2_rp2350b_m33_w.overlay | 17 ----------------- src/samples/demo/zephyr/fstab.overlay | 16 ++++++++++++++++ src/samples/mini/zephyr/CMakeLists.txt | 3 +++ .../mini/zephyr/boards/native_sim_64.overlay | 17 ----------------- .../boards/pico_plus2_rp2350b_m33.overlay | 17 ----------------- .../boards/pico_plus2_rp2350b_m33_w.overlay | 17 ----------------- src/samples/mini/zephyr/fstab.overlay | 16 ++++++++++++++++ src/samples/supervisor/zephyr/CMakeLists.txt | 3 +++ .../zephyr/boards/b_u585i_iot02a.overlay | 17 ----------------- .../zephyr/boards/native_sim_64.overlay | 17 ----------------- .../boards/pico_plus2_rp2350b_m33.overlay | 17 ----------------- .../boards/pico_plus2_rp2350b_m33_w.overlay | 17 ----------------- src/samples/supervisor/zephyr/fstab.overlay | 16 ++++++++++++++++ 16 files changed, 57 insertions(+), 170 deletions(-) create mode 100644 src/samples/demo/zephyr/fstab.overlay create mode 100644 src/samples/mini/zephyr/fstab.overlay create mode 100644 src/samples/supervisor/zephyr/fstab.overlay diff --git a/src/samples/demo/zephyr/CMakeLists.txt b/src/samples/demo/zephyr/CMakeLists.txt index 4371bd1c..4f07039b 100644 --- a/src/samples/demo/zephyr/CMakeLists.txt +++ b/src/samples/demo/zephyr/CMakeLists.txt @@ -6,6 +6,9 @@ cmake_minimum_required(VERSION 3.20.0) # comment out to use the ocre module provided by Zephyr list(APPEND ZEPHYR_EXTRA_MODULES ${CMAKE_CURRENT_LIST_DIR}/../../../..) +# append the fstab overlay file to the list of DTC overlay files +list(APPEND EXTRA_DTC_OVERLAY_FILE fstab.overlay) + include(../demo_containers.cmake) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) diff --git a/src/samples/demo/zephyr/boards/native_sim_64.overlay b/src/samples/demo/zephyr/boards/native_sim_64.overlay index e4e1c86c..eb2c157d 100644 --- a/src/samples/demo/zephyr/boards/native_sim_64.overlay +++ b/src/samples/demo/zephyr/boards/native_sim_64.overlay @@ -1,20 +1,3 @@ -/ { - fstab { - compatible = "zephyr,fstab"; - lfs1: lfs1 { - compatible = "zephyr,fstab,littlefs"; - read-size = <256>; - prog-size = <256>; - cache-size = <256>; - lookahead-size = <256>; - block-cycles = <512>; - partition = <&storage_partition>; - mount-point = "/lfs"; - automount; - }; - }; -}; - &flash0 { reg = < 0x0 DT_SIZE_M(32) >; }; diff --git a/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33.overlay b/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33.overlay index 383637bc..24e3edbb 100644 --- a/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33.overlay +++ b/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33.overlay @@ -10,20 +10,3 @@ }; }; }; - -/ { - fstab { - compatible = "zephyr,fstab"; - lfs1: lfs1 { - compatible = "zephyr,fstab,littlefs"; - read-size = <256>; - prog-size = <256>; - cache-size = <256>; - lookahead-size = <256>; - block-cycles = <512>; - partition = <&storage_partition>; - mount-point = "/lfs"; - automount; - }; - }; -}; diff --git a/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay b/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay index 383637bc..24e3edbb 100644 --- a/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay +++ b/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay @@ -10,20 +10,3 @@ }; }; }; - -/ { - fstab { - compatible = "zephyr,fstab"; - lfs1: lfs1 { - compatible = "zephyr,fstab,littlefs"; - read-size = <256>; - prog-size = <256>; - cache-size = <256>; - lookahead-size = <256>; - block-cycles = <512>; - partition = <&storage_partition>; - mount-point = "/lfs"; - automount; - }; - }; -}; diff --git a/src/samples/demo/zephyr/fstab.overlay b/src/samples/demo/zephyr/fstab.overlay new file mode 100644 index 00000000..a986be8d --- /dev/null +++ b/src/samples/demo/zephyr/fstab.overlay @@ -0,0 +1,16 @@ +/ { + fstab { + compatible = "zephyr,fstab"; + lfs1: lfs1 { + compatible = "zephyr,fstab,littlefs"; + read-size = <256>; + prog-size = <256>; + cache-size = <256>; + lookahead-size = <256>; + block-cycles = <512>; + partition = <&storage_partition>; + mount-point = "/lfs"; + automount; + }; + }; +}; diff --git a/src/samples/mini/zephyr/CMakeLists.txt b/src/samples/mini/zephyr/CMakeLists.txt index 17efe0f7..90ca467f 100644 --- a/src/samples/mini/zephyr/CMakeLists.txt +++ b/src/samples/mini/zephyr/CMakeLists.txt @@ -6,6 +6,9 @@ cmake_minimum_required(VERSION 3.20.0) # comment out to use the ocre module provided by Zephyr list(APPEND ZEPHYR_EXTRA_MODULES ${CMAKE_CURRENT_LIST_DIR}/../../../..) +# append the fstab overlay file to the list of DTC overlay files +list(APPEND EXTRA_DTC_OVERLAY_FILE fstab.overlay) + find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project (ocre_sample_mini) diff --git a/src/samples/mini/zephyr/boards/native_sim_64.overlay b/src/samples/mini/zephyr/boards/native_sim_64.overlay index e4e1c86c..eb2c157d 100644 --- a/src/samples/mini/zephyr/boards/native_sim_64.overlay +++ b/src/samples/mini/zephyr/boards/native_sim_64.overlay @@ -1,20 +1,3 @@ -/ { - fstab { - compatible = "zephyr,fstab"; - lfs1: lfs1 { - compatible = "zephyr,fstab,littlefs"; - read-size = <256>; - prog-size = <256>; - cache-size = <256>; - lookahead-size = <256>; - block-cycles = <512>; - partition = <&storage_partition>; - mount-point = "/lfs"; - automount; - }; - }; -}; - &flash0 { reg = < 0x0 DT_SIZE_M(32) >; }; diff --git a/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33.overlay b/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33.overlay index 383637bc..24e3edbb 100644 --- a/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33.overlay +++ b/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33.overlay @@ -10,20 +10,3 @@ }; }; }; - -/ { - fstab { - compatible = "zephyr,fstab"; - lfs1: lfs1 { - compatible = "zephyr,fstab,littlefs"; - read-size = <256>; - prog-size = <256>; - cache-size = <256>; - lookahead-size = <256>; - block-cycles = <512>; - partition = <&storage_partition>; - mount-point = "/lfs"; - automount; - }; - }; -}; diff --git a/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay b/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay index 383637bc..24e3edbb 100644 --- a/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay +++ b/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay @@ -10,20 +10,3 @@ }; }; }; - -/ { - fstab { - compatible = "zephyr,fstab"; - lfs1: lfs1 { - compatible = "zephyr,fstab,littlefs"; - read-size = <256>; - prog-size = <256>; - cache-size = <256>; - lookahead-size = <256>; - block-cycles = <512>; - partition = <&storage_partition>; - mount-point = "/lfs"; - automount; - }; - }; -}; diff --git a/src/samples/mini/zephyr/fstab.overlay b/src/samples/mini/zephyr/fstab.overlay new file mode 100644 index 00000000..a986be8d --- /dev/null +++ b/src/samples/mini/zephyr/fstab.overlay @@ -0,0 +1,16 @@ +/ { + fstab { + compatible = "zephyr,fstab"; + lfs1: lfs1 { + compatible = "zephyr,fstab,littlefs"; + read-size = <256>; + prog-size = <256>; + cache-size = <256>; + lookahead-size = <256>; + block-cycles = <512>; + partition = <&storage_partition>; + mount-point = "/lfs"; + automount; + }; + }; +}; diff --git a/src/samples/supervisor/zephyr/CMakeLists.txt b/src/samples/supervisor/zephyr/CMakeLists.txt index dd77b616..8a981528 100644 --- a/src/samples/supervisor/zephyr/CMakeLists.txt +++ b/src/samples/supervisor/zephyr/CMakeLists.txt @@ -6,6 +6,9 @@ cmake_minimum_required(VERSION 3.20.0) # comment out to use the ocre module provided by zephyr list(APPEND ZEPHYR_EXTRA_MODULES ${CMAKE_CURRENT_LIST_DIR}/../../../..) +# append the fstab overlay file to the list of DTC overlay files +list(APPEND EXTRA_DTC_OVERLAY_FILE fstab.overlay) + find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project (ocre_sample_supervisor) diff --git a/src/samples/supervisor/zephyr/boards/b_u585i_iot02a.overlay b/src/samples/supervisor/zephyr/boards/b_u585i_iot02a.overlay index a27fe2e9..2804dcf8 100644 --- a/src/samples/supervisor/zephyr/boards/b_u585i_iot02a.overlay +++ b/src/samples/supervisor/zephyr/boards/b_u585i_iot02a.overlay @@ -122,23 +122,6 @@ }; }; -/ { - fstab { - compatible = "zephyr,fstab"; - lfs1: lfs1 { - compatible = "zephyr,fstab,littlefs"; - read-size = <256>; - prog-size = <256>; - cache-size = <256>; - lookahead-size = <256>; - block-cycles = <512>; - partition = <&storage_partition>; - mount-point = "/lfs"; - automount; - }; - }; -}; - &die_temp { status = "disabled"; }; diff --git a/src/samples/supervisor/zephyr/boards/native_sim_64.overlay b/src/samples/supervisor/zephyr/boards/native_sim_64.overlay index e4e1c86c..eb2c157d 100644 --- a/src/samples/supervisor/zephyr/boards/native_sim_64.overlay +++ b/src/samples/supervisor/zephyr/boards/native_sim_64.overlay @@ -1,20 +1,3 @@ -/ { - fstab { - compatible = "zephyr,fstab"; - lfs1: lfs1 { - compatible = "zephyr,fstab,littlefs"; - read-size = <256>; - prog-size = <256>; - cache-size = <256>; - lookahead-size = <256>; - block-cycles = <512>; - partition = <&storage_partition>; - mount-point = "/lfs"; - automount; - }; - }; -}; - &flash0 { reg = < 0x0 DT_SIZE_M(32) >; }; diff --git a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33.overlay b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33.overlay index 383637bc..24e3edbb 100644 --- a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33.overlay +++ b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33.overlay @@ -10,20 +10,3 @@ }; }; }; - -/ { - fstab { - compatible = "zephyr,fstab"; - lfs1: lfs1 { - compatible = "zephyr,fstab,littlefs"; - read-size = <256>; - prog-size = <256>; - cache-size = <256>; - lookahead-size = <256>; - block-cycles = <512>; - partition = <&storage_partition>; - mount-point = "/lfs"; - automount; - }; - }; -}; diff --git a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay index 383637bc..24e3edbb 100644 --- a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay +++ b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay @@ -10,20 +10,3 @@ }; }; }; - -/ { - fstab { - compatible = "zephyr,fstab"; - lfs1: lfs1 { - compatible = "zephyr,fstab,littlefs"; - read-size = <256>; - prog-size = <256>; - cache-size = <256>; - lookahead-size = <256>; - block-cycles = <512>; - partition = <&storage_partition>; - mount-point = "/lfs"; - automount; - }; - }; -}; diff --git a/src/samples/supervisor/zephyr/fstab.overlay b/src/samples/supervisor/zephyr/fstab.overlay new file mode 100644 index 00000000..a986be8d --- /dev/null +++ b/src/samples/supervisor/zephyr/fstab.overlay @@ -0,0 +1,16 @@ +/ { + fstab { + compatible = "zephyr,fstab"; + lfs1: lfs1 { + compatible = "zephyr,fstab,littlefs"; + read-size = <256>; + prog-size = <256>; + cache-size = <256>; + lookahead-size = <256>; + block-cycles = <512>; + partition = <&storage_partition>; + mount-point = "/lfs"; + automount; + }; + }; +}; From c3d0aa8393c2b57b15ad643ab1a36dcc73a1ab5e Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 17 Dec 2025 20:01:16 +0100 Subject: [PATCH 176/234] feat(shell): ocre version command Signed-off-by: Marco Casaroli --- src/ocre/ocre.c | 8 ++++---- src/shell/shell.c | 6 +++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/ocre/ocre.c b/src/ocre/ocre.c index 4af06ee5..01afc056 100644 --- a/src/ocre/ocre.c +++ b/src/ocre/ocre.c @@ -38,10 +38,10 @@ static struct runtime_node *runtimes = NULL; int ocre_initialize(const struct ocre_runtime_vtable *const vtable[]) { - LOG_INF("Initializing Ocre %s", ocre_build_configuration.version); - LOG_INF("Build Commit ID: %s", ocre_build_configuration.commit_id); - LOG_INF("Build Info: %s", ocre_build_configuration.build_info); - LOG_INF("Build Date: %s", ocre_build_configuration.build_date); + LOG_INF("Ocre version %s", ocre_build_configuration.version); + LOG_INF("Commit ID: %s", ocre_build_configuration.commit_id); + LOG_INF("Build information: %s", ocre_build_configuration.build_info); + LOG_INF("Build date: %s", ocre_build_configuration.build_date); /* Add WAMR runtime to the list */ diff --git a/src/shell/shell.c b/src/shell/shell.c index 8105ce94..c7d99ff3 100644 --- a/src/shell/shell.c +++ b/src/shell/shell.c @@ -22,7 +22,11 @@ static int print_version(struct ocre_context *ctx, const char *argv0, int argc, char **argv) { - fprintf(stdout, "Ocre version 1.0\n"); + fprintf(stdout, "Ocre version: %s\n", ocre_build_configuration.version); + fprintf(stdout, "Commit ID: %s\n", ocre_build_configuration.commit_id); + fprintf(stdout, "Build information: %s\n", ocre_build_configuration.build_info); + fprintf(stdout, "Build date: %s\n", ocre_build_configuration.build_date); + return 0; } From beb3a244b881d6a599a4bfcc1a871dd1bad41d62 Mon Sep 17 00:00:00 2001 From: SorinO Date: Thu, 18 Dec 2025 16:00:30 +0200 Subject: [PATCH 177/234] fix ocre gpio Signed-off-by: Marco Casaroli --- src/runtime/wamr/ocre_api/CMakeLists.txt | 2 +- .../wamr/ocre_api/ocre_gpio/ocre_gpio.c | 19 +++++++++++++------ .../wamr/ocre_api/ocre_gpio/ocre_gpio.h | 4 ++-- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/runtime/wamr/ocre_api/CMakeLists.txt b/src/runtime/wamr/ocre_api/CMakeLists.txt index f4d40a14..e787511a 100644 --- a/src/runtime/wamr/ocre_api/CMakeLists.txt +++ b/src/runtime/wamr/ocre_api/CMakeLists.txt @@ -12,7 +12,7 @@ target_sources(OcreRuntimeAPI core/core_timer.c core/core_mutex.c core/core_memory.c - + ocre_gpio/ocre_gpio.c ) target_link_libraries(OcreRuntimeAPI diff --git a/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.c b/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.c index 214720a4..4a7c9cb4 100644 --- a/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.c +++ b/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.c @@ -14,6 +14,11 @@ #include #include +#include + +#include "../ocre_common.h" +#include "ocre_gpio.h" + LOG_MODULE_REGISTER(ocre_gpio, CONFIG_OCRE_LOG_LEVEL); typedef struct { @@ -135,7 +140,7 @@ int ocre_gpio_init(void) return 0; } -int ocre_gpio_configure(const ocre_gpio_config_t *config) +int ocre_gpio_configure(wasm_exec_env_t exec_env, const ocre_gpio_config_t *config) { if (!gpio_system_initialized || !config || config->pin >= CONFIG_OCRE_GPIO_PINS_PER_PORT || config->port_idx >= CONFIG_OCRE_GPIO_MAX_PORTS || !port_ready[config->port_idx]) { @@ -154,11 +159,13 @@ int ocre_gpio_configure(const ocre_gpio_config_t *config) LOG_ERR("Failed to configure GPIO pin %d on port %d: %d", pin, port_idx, ret); return ret; } - wasm_module_inst_t module_inst = ocre_get_current_module(); + + wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); if (!module_inst) { LOG_ERR("No current module instance for GPIO configuration"); return -EINVAL; } + int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; if (global_pin >= CONFIG_OCRE_GPIO_MAX_PINS) { LOG_ERR("Global pin %d exceeds max %d", global_pin, CONFIG_OCRE_GPIO_MAX_PINS); @@ -323,7 +330,7 @@ int ocre_gpio_wasm_configure(wasm_exec_env_t exec_env, int port, int pin, int di return -EINVAL; } ocre_gpio_config_t config = {.pin = pin, .port_idx = port, .direction = direction}; - return ocre_gpio_configure(&config); + return ocre_gpio_configure(exec_env, &config); } int ocre_gpio_wasm_set(wasm_exec_env_t exec_env, int port, int pin, int state) @@ -559,7 +566,7 @@ static int resolve_gpio_alias(const char *name, int *port_idx, gpio_pin_t *pin) return 0; } -int ocre_gpio_configure_by_name(const char *name, ocre_gpio_direction_t direction) +int ocre_gpio_configure_by_name(wasm_exec_env_t exec_env, const char *name, ocre_gpio_direction_t direction) { if (!name) { LOG_ERR("Invalid name parameter"); @@ -575,7 +582,7 @@ int ocre_gpio_configure_by_name(const char *name, ocre_gpio_direction_t directio ocre_gpio_config_t config = {.pin = pin, .port_idx = port_idx, .direction = direction}; - return ocre_gpio_configure(&config); + return ocre_gpio_configure(exec_env, &config); } int ocre_gpio_set_by_name(const char *name, ocre_gpio_pin_state_t state) @@ -646,7 +653,7 @@ int ocre_gpio_wasm_configure_by_name(wasm_exec_env_t exec_env, const char *name, } LOG_INF("Configuring GPIO by name: %s, direction=%d", name, direction); - return ocre_gpio_configure_by_name(name, direction); + return ocre_gpio_configure_by_name(exec_env, name, direction); } int ocre_gpio_wasm_set_by_name(wasm_exec_env_t exec_env, const char *name, int state) diff --git a/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.h b/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.h index 74258537..4164ed06 100644 --- a/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.h +++ b/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.h @@ -68,7 +68,7 @@ int ocre_gpio_init(void); * @param config GPIO pin configuration * @return 0 on success, negative error code on failure */ -int ocre_gpio_configure(const ocre_gpio_config_t *config); +int ocre_gpio_configure(wasm_exec_env_t exec_env, const ocre_gpio_config_t *config); /** * Set GPIO pin state. @@ -133,7 +133,7 @@ void ocre_gpio_set_dispatcher(wasm_exec_env_t exec_env); * @param direction GPIO direction (OCRE_GPIO_DIR_INPUT or OCRE_GPIO_DIR_OUTPUT) * @return int 0 on success, negative error code on failure */ -int ocre_gpio_configure_by_name(const char *name, ocre_gpio_direction_t direction); +int ocre_gpio_configure_by_name(wasm_exec_env_t exec_env, const char *name, ocre_gpio_direction_t direction); /** * @brief Set a GPIO pin state by alias name From 5164aaaad886d649d6532025c8aab8f6d270a95e Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 18 Dec 2025 21:05:11 +0100 Subject: [PATCH 178/234] fix(ocre): remove undefined behavior on cleanup Now, the Ocre library will track all the created contexts and deinitialize them when the library is deinitialized. We now need a mutex to protect the contexts list. Signed-off-by: Marco Casaroli --- src/ocre/context.c | 231 +++++----------------------- src/ocre/context.h | 2 + src/ocre/include/ocre/ocre.h | 10 +- src/ocre/ocre.c | 289 +++++++++++++++++++++++++++++++++-- src/samples/demo/main.c | 2 +- src/samples/mini/main.c | 2 +- 6 files changed, 328 insertions(+), 208 deletions(-) diff --git a/src/ocre/context.c b/src/ocre/context.c index d3862156..6287f772 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -23,7 +23,7 @@ LOG_MODULE_REGISTER(context, CONFIG_OCRE_LOG_LEVEL); struct ocre_context { pthread_mutex_t mutex; - char *working_directory; + const char *working_directory; struct container_node *containers; }; @@ -33,144 +33,46 @@ struct container_node { struct container_node *next; /* needed for singly- or doubly-linked lists */ }; -#if CONFIG_OCRE_FILESYSTEM -static int delete_container_workdirs(const char *working_directory) -{ - int ret = -1; - DIR *d = NULL; - const struct dirent *dir = NULL; - - char *containers_path = malloc(strlen(working_directory) + strlen("/containers") + 1); - if (!containers_path) { - LOG_ERR("Failed to allocate memory for container workdir path"); - return -1; - } - - sprintf(containers_path, "%s/containers", working_directory); - - d = opendir(containers_path); - if (!d) { - fprintf(stderr, "Failed to open directory '%s'\n", containers_path); - goto finish; - } - - while ((dir = readdir(d)) != NULL) { - - if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, "..")) { - continue; - } - - char *container_workdir_path = malloc(strlen(containers_path) + strlen(dir->d_name) + 2); - if (!container_workdir_path) { - fprintf(stderr, "Failed to allocate memory for container workdir path\n"); - goto finish; - } - - strcpy(container_workdir_path, containers_path); - strcat(container_workdir_path, "/"); - strcat(container_workdir_path, dir->d_name); - - if (rm_rf(container_workdir_path)) { - fprintf(stderr, "Failed to remove container workdir '%s'\n", container_workdir_path); - free(container_workdir_path); - goto finish; - } - - free(container_workdir_path); - } - - ret = 0; - -finish: - if (d) { - closedir(d); - } - - free(containers_path); - - return ret; -} -#endif - -static int create_dir_if_not_exists(const char *path) +static int ocre_context_remove_container_locked(struct ocre_context *context, struct ocre_container *container) { int rc; - struct stat st; - - rc = stat(path, &st); - if (rc && errno == ENOENT) { - LOG_INF("Directory '%s' does not exist, creating...", path); - rc = mkdir(path, 0755); - if (rc) { - LOG_ERR("Failed to create directory '%s': errno=%d", path, errno); - return -1; - } - } else if (!rc && !S_ISDIR(st.st_mode)) { - LOG_ERR("Path '%s' is not a directory", path); - return -1; - } else if (!rc && S_ISDIR(st.st_mode)) { - LOG_INF("Directory '%s' already exists", path); - } - - return 0; -} - -static int populate_ocre_workdir(const char *working_directory) -{ - int rc = -1; - char *containers_path = NULL; - char *images_path = NULL; - - rc = create_dir_if_not_exists(working_directory); - if (rc) { - LOG_ERR("Failed to create Ocre working directory '%s': errno=%d", working_directory, errno); - return -1; - } - - containers_path = malloc(strlen(working_directory) + strlen("/containers") + 1); - if (!containers_path) { - LOG_ERR("Failed to allocate memory for container workdir path"); - goto finish; - } + struct container_node *node = NULL; + struct container_node *elt = NULL; - sprintf(containers_path, "%s/containers", working_directory); + LL_FOREACH_SAFE(context->containers, node, elt) + { + if (node->container == container) { + rc = ocre_container_destroy(container); + if (rc) { + LOG_ERR("Failed to destroy container: rc=%d", rc); + return -1; + } - rc = create_dir_if_not_exists(containers_path); - if (rc) { - LOG_ERR("Failed to create Ocre containers directory '%s': errno=%d", containers_path, errno); - goto finish; - } +#if CONFIG_OCRE_FILESYSTEM + if (node->working_directory) { + rc = rm_rf(node->working_directory); + if (rc) { + LOG_ERR("Failed to remove container working directory '%s': rc=%d", + node->working_directory, rc); + return -1; + } + } +#endif - images_path = malloc(strlen(working_directory) + strlen("/images") + 1); - if (!images_path) { - LOG_ERR("Failed to allocate memory for container workdir path"); - goto finish; - } + LL_DELETE(context->containers, node); - sprintf(images_path, "%s/images", working_directory); + free(node->working_directory); + free(node); - rc = create_dir_if_not_exists(images_path); - if (rc) { - LOG_ERR("Failed to create Ocre images directory '%s': errno=%d", images_path, errno); - goto finish; + return 0; + } } - -finish: - free(containers_path); - free(images_path); - - return rc; } -struct ocre_context *ocre_create_context(const char *workdir) +struct ocre_context *ocre_context_create(const char *workdir) { int rc; - if (!workdir) { - workdir = CONFIG_OCRE_DEFAULT_WORKING_DIRECTORY; - LOG_INF("Using default working directory: %s", workdir); - } - struct ocre_context *context = malloc(sizeof(struct ocre_context)); if (!context) { LOG_ERR("Failed to allocate memory for context: errno=%d", errno); @@ -179,30 +81,16 @@ struct ocre_context *ocre_create_context(const char *workdir) memset(context, 0, sizeof(struct ocre_context)); - context->working_directory = strdup(workdir); - if (!context->working_directory) { - LOG_ERR("Failed to allocate memory for working directory: errno=%d", errno); - goto error; - } - - /* Initialize working directory */ - - rc = populate_ocre_workdir(context->working_directory); - if (rc) { - LOG_ERR("Failed to populate Ocre working directory: rc=%d", rc); - goto error; - } - -#if CONFIG_OCRE_FILESYSTEM - delete_container_workdirs(context->working_directory); -#endif - rc = pthread_mutex_init(&context->mutex, NULL); if (rc) { LOG_ERR("Failed to initialize context mutex: rc=%d", rc); goto error; } + /* Set working directory */ + + context->working_directory = workdir; + /* Initialize containers list */ context->containers = NULL; @@ -210,8 +98,6 @@ struct ocre_context *ocre_create_context(const char *workdir) return context; error: - free(context->working_directory); - free(context); return NULL; @@ -237,15 +123,10 @@ struct ocre_container *ocre_context_get_container_by_id_locked(const struct ocre return NULL; } -void ocre_context_destroy(struct ocre_context *context) +int ocre_context_destroy(struct ocre_context *context) { struct container_node *node; - if (!context) { - LOG_ERR("Invalid context"); - return; - } - /* Send kill event to all containers */ LL_FOREACH(context->containers, node) @@ -264,18 +145,18 @@ void ocre_context_destroy(struct ocre_context *context) LL_FOREACH(context->containers, node) { - ocre_context_remove_container(context, node->container); + ocre_context_remove_container_locked(context, node->container); } - int rc; - rc = pthread_mutex_destroy(&context->mutex); + int rc = pthread_mutex_destroy(&context->mutex); if (rc) { LOG_ERR("Failed to destroy context mutex: rc=%d", rc); + return -1; } - free(context->working_directory); - free(context); + + return 0; }; struct ocre_container *ocre_context_create_container(struct ocre_context *context, const char *image, @@ -427,7 +308,6 @@ struct ocre_container *ocre_context_create_container(struct ocre_context *contex int ocre_context_remove_container(struct ocre_context *context, struct ocre_container *container) { int rc = -1; - struct container_node *node = NULL; if (!context || !container) { LOG_ERR("Invalid arguments"); @@ -440,44 +320,17 @@ int ocre_context_remove_container(struct ocre_context *context, struct ocre_cont return -1; } - LL_FOREACH(context->containers, node) - { - if (node->container == container) { - rc = ocre_container_destroy(container); - if (rc) { - LOG_ERR("Failed to destroy container: rc=%d", rc); - goto finish; - } - -#if CONFIG_OCRE_FILESYSTEM - if (node->working_directory) { - rc = rm_rf(node->working_directory); - if (rc) { - LOG_ERR("Failed to remove container working directory '%s': rc=%d", - node->working_directory, rc); - goto finish; - } - } -#endif - - LL_DELETE(context->containers, node); - - free(node->working_directory); - free(node); - - rc = 0; - - goto finish; - } + rc = ocre_context_remove_container_locked(context, container); + if (rc) { + LOG_ERR("Failed to remove container: rc=%d", rc); } -finish: { int ret = pthread_mutex_unlock(&context->mutex); if (ret) { LOG_ERR("Failed to unlock context mutex: rc=%d", rc); return -1; } -} + return rc; } diff --git a/src/ocre/context.h b/src/ocre/context.h index a170dd85..db8eed0c 100644 --- a/src/ocre/context.h +++ b/src/ocre/context.h @@ -1,3 +1,5 @@ struct ocre_context; +struct ocre_context *ocre_context_create(const char *workdir); +int ocre_context_destroy(struct ocre_context *context); struct ocre_container *ocre_context_get_container_by_id_locked(const struct ocre_context *context, const char *id); diff --git a/src/ocre/include/ocre/ocre.h b/src/ocre/include/ocre/ocre.h index 7075eca1..a6f68bd7 100644 --- a/src/ocre/include/ocre/ocre.h +++ b/src/ocre/include/ocre/ocre.h @@ -93,7 +93,7 @@ extern const struct ocre_config ocre_build_configuration; * @headerfile ocre.h * @brief Ocre Context * - * The context is created by ocre_context_create() and destroyed by ocre_context_destroy(). It is used to interact with + * The context is created by ocre_create_context() and destroyed by ocre_destroy_context(). It is used to interact with * Ocre Library and passed around as pointers. * * The Ocre Context is a manager for a set of containers on their own runtime engines. @@ -236,16 +236,14 @@ struct ocre_context *ocre_create_context(const char *workdir); * * @param context A pointer to the Ocre Context to destroy. * - * Any errors will be ignored. + * @return 0 on success, non-zero on failure */ -void ocre_context_destroy(struct ocre_context *context); +int ocre_destroy_context(struct ocre_context *context); /** * @brief Deinitializes the Ocre Library * - * Deinitializes the Ocre Library. Care must be taken to ensure that all contexts have been destroyed before calling - * this function. Deinitialization of the library while contexts are still instantiated is considered an error and - * results in undefined behavior. + * Deinitializes the Ocre Library, destroying all contexts and containers. * * Any errors will be ignored. */ diff --git a/src/ocre/ocre.c b/src/ocre/ocre.c index 01afc056..ff305f24 100644 --- a/src/ocre/ocre.c +++ b/src/ocre/ocre.c @@ -1,18 +1,21 @@ #include +#include #include #include #include - -#include +#include +#include +#include #include - #include +#include +#include +#include "context.h" +#include "util/rm_rf.h" #include "uthash/utlist.h" -#include - #include "commit_id.h" #include "version.h" @@ -34,7 +37,247 @@ struct runtime_node { struct runtime_node *next; }; +struct context_node { + struct ocre_context *context; + char *working_directory; + struct context_node *next; +}; + static struct runtime_node *runtimes = NULL; +static struct context_node *contexts = NULL; +static pthread_mutex_t contexts_mutex = PTHREAD_MUTEX_INITIALIZER; + +static int create_dir_if_not_exists(const char *path) +{ + int rc; + struct stat st; + + rc = stat(path, &st); + if (rc && errno == ENOENT) { + LOG_INF("Directory '%s' does not exist, creating...", path); + rc = mkdir(path, 0755); + if (rc) { + LOG_ERR("Failed to create directory '%s': errno=%d", path, errno); + return -1; + } + } else if (!rc && !S_ISDIR(st.st_mode)) { + LOG_ERR("Path '%s' is not a directory", path); + return -1; + } else if (!rc && S_ISDIR(st.st_mode)) { + LOG_INF("Directory '%s' already exists", path); + } + + return 0; +} + +static int populate_context_workdir(const char *working_directory) +{ + int rc = -1; + char *containers_path = NULL; + char *images_path = NULL; + + rc = create_dir_if_not_exists(working_directory); + if (rc) { + LOG_ERR("Failed to create Ocre working directory '%s': errno=%d", working_directory, errno); + return -1; + } + + containers_path = malloc(strlen(working_directory) + strlen("/containers") + 1); + if (!containers_path) { + LOG_ERR("Failed to allocate memory for container workdir path"); + goto finish; + } + + sprintf(containers_path, "%s/containers", working_directory); + + rc = create_dir_if_not_exists(containers_path); + if (rc) { + LOG_ERR("Failed to create Ocre containers directory '%s': errno=%d", containers_path, errno); + goto finish; + } + + images_path = malloc(strlen(working_directory) + strlen("/images") + 1); + if (!images_path) { + LOG_ERR("Failed to allocate memory for container workdir path"); + goto finish; + } + + sprintf(images_path, "%s/images", working_directory); + + rc = create_dir_if_not_exists(images_path); + if (rc) { + LOG_ERR("Failed to create Ocre images directory '%s': errno=%d", images_path, errno); + goto finish; + } + +finish: + free(containers_path); + free(images_path); + + return rc; +} + +#if CONFIG_OCRE_FILESYSTEM +static int delete_container_workdirs(const char *working_directory) +{ + int ret = -1; + DIR *d = NULL; + const struct dirent *dir = NULL; + + char *containers_path = malloc(strlen(working_directory) + strlen("/containers") + 1); + if (!containers_path) { + LOG_ERR("Failed to allocate memory for container workdir path"); + return -1; + } + + sprintf(containers_path, "%s/containers", working_directory); + + d = opendir(containers_path); + if (!d) { + fprintf(stderr, "Failed to open directory '%s'\n", containers_path); + goto finish; + } + + while ((dir = readdir(d)) != NULL) { + if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, "..")) { + continue; + } + + char *container_workdir_path = malloc(strlen(containers_path) + strlen(dir->d_name) + 2); + if (!container_workdir_path) { + fprintf(stderr, "Failed to allocate memory for container workdir path\n"); + goto finish; + } + + strcpy(container_workdir_path, containers_path); + strcat(container_workdir_path, "/"); + strcat(container_workdir_path, dir->d_name); + + if (rm_rf(container_workdir_path)) { + fprintf(stderr, "Failed to remove container workdir '%s'\n", container_workdir_path); + free(container_workdir_path); + goto finish; + } + + free(container_workdir_path); + } + + ret = 0; + +finish: + if (d) { + closedir(d); + } + + free(containers_path); + + return ret; +} +#endif + +static int ocre_destroy_context_locked(struct ocre_context *context) +{ + int rc; + struct context_node *node = NULL; + struct context_node *elt = NULL; + + LL_FOREACH_SAFE(contexts, node, elt) + { + if (node->context == context) { + rc = ocre_context_destroy(context); + if (rc) { + LOG_ERR("Failed to destroy context: rc=%d", rc); + return rc; + } + + LL_DELETE(contexts, node); + + free(node->working_directory); + free(node); + + return 0; + } + } +} + +struct ocre_context *ocre_create_context(const char *workdir) +{ + int rc; + + if (!workdir) { + workdir = CONFIG_OCRE_DEFAULT_WORKING_DIRECTORY; + LOG_INF("Using default working directory: %s", workdir); + } + + // TODO check if working directory is already taken + + struct context_node *node = malloc(sizeof(struct context_node)); + if (!node) { + LOG_ERR("Failed to allocate memory for context node: errno=%d", errno); + return NULL; + } + + memset(node, 0, sizeof(struct context_node)); + + node->working_directory = strdup(workdir); + if (!node->working_directory) { + LOG_ERR("Failed to allocate memory for working directory: errno=%d", errno); + goto error; + } + + /* Initialize working directory */ + + rc = populate_context_workdir(node->working_directory); + if (rc) { + LOG_ERR("Failed to populate Ocre working directory: rc=%d", rc); + goto error; + } + +#if CONFIG_OCRE_FILESYSTEM + delete_container_workdirs(node->working_directory); +#endif + + node->context = ocre_context_create(node->working_directory); + if (!node->context) { + LOG_ERR("Failed to create Ocre context"); + goto error; + } + + return node->context; + +error: + free(node->working_directory); + + free(node); + + return NULL; +}; + +int ocre_destroy_context(struct ocre_context *context) +{ + int rc = -1; + + if (!context) { + LOG_ERR("Invalid context"); + return -1; + } + + rc = pthread_mutex_lock(&contexts_mutex); + if (rc) { + LOG_ERR("Failed to lock mutex: rc=%d", rc); + return -1; + } + + rc = ocre_destroy_context_locked(context); + + rc = pthread_mutex_unlock(&contexts_mutex); + if (rc) { + LOG_ERR("Failed to unlock mutex: rc=%d", rc); + return -1; + } + + return rc; +}; int ocre_initialize(const struct ocre_runtime_vtable *const vtable[]) { @@ -43,6 +286,17 @@ int ocre_initialize(const struct ocre_runtime_vtable *const vtable[]) LOG_INF("Build information: %s", ocre_build_configuration.build_info); LOG_INF("Build date: %s", ocre_build_configuration.build_date); + /* Reinitialize the static variables */ + + runtimes = NULL; + contexts = NULL; + + int rc = pthread_mutex_init(&contexts_mutex, NULL); + if (rc) { + LOG_ERR("Failed to initialize Ocre mutex: rc=%d", rc); + return -1; + } + /* Add WAMR runtime to the list */ struct runtime_node *wamr = malloc(sizeof(struct runtime_node)); @@ -112,17 +366,30 @@ const struct ocre_runtime_vtable *ocre_get_runtime(const char *name) void ocre_deinitialize(void) { - struct runtime_node *elt, *tmp; + struct context_node *c_node; + struct runtime_node *r_elt, *r_tmp; - LL_FOREACH_SAFE(runtimes, elt, tmp) + LL_FOREACH(contexts, c_node) { - if (elt->runtime->deinit && elt->runtime->deinit()) { - LOG_INF("Failed to deinitialize '%s'", elt->runtime->runtime_name); + if (ocre_destroy_context_locked(c_node->context)) { + LOG_ERR("Failed to destroy context %p", c_node->context); } + } - LL_DELETE(runtimes, elt); + LL_FOREACH_SAFE(runtimes, r_elt, r_tmp) + { + if (r_elt->runtime->deinit && r_elt->runtime->deinit()) { + LOG_INF("Failed to deinitialize '%s'", r_elt->runtime->runtime_name); + } + + LL_DELETE(runtimes, r_elt); + + free(r_elt); + } - free(elt); + int rc = pthread_mutex_destroy(&contexts_mutex); + if (rc) { + LOG_ERR("Failed to destroy context mutex: rc=%d", rc); } } diff --git a/src/samples/demo/main.c b/src/samples/demo/main.c index 58a4ef74..71cb43ed 100644 --- a/src/samples/demo/main.c +++ b/src/samples/demo/main.c @@ -149,7 +149,7 @@ int main(int argc, char *argv[]) return 1; } - ocre_context_destroy(ocre); + ocre_destroy_context(ocre); ocre_deinitialize(); diff --git a/src/samples/mini/main.c b/src/samples/mini/main.c index 8125237f..3fe6f693 100644 --- a/src/samples/mini/main.c +++ b/src/samples/mini/main.c @@ -104,7 +104,7 @@ int main(int argc, char *argv[]) return 1; } - ocre_context_destroy(ocre); + ocre_destroy_context(ocre); ocre_deinitialize(); From 6f8ab94a1b1e8bbea8005bca8787398b0e54e2f1 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Fri, 19 Dec 2025 00:01:38 +0100 Subject: [PATCH 179/234] feat(ocre): do not accept two contexts with same workdir Now that we track all the contexts, we can ensure no more than one context will be initialized with the same workdir, thus removing another undefined behavior. Signed-off-by: Marco Casaroli --- src/ocre/include/ocre/ocre.h | 2 +- src/ocre/ocre.c | 71 +++++++++++++++++++++++++----------- 2 files changed, 50 insertions(+), 23 deletions(-) diff --git a/src/ocre/include/ocre/ocre.h b/src/ocre/include/ocre/ocre.h index a6f68bd7..0acecaa8 100644 --- a/src/ocre/include/ocre/ocre.h +++ b/src/ocre/include/ocre/ocre.h @@ -221,7 +221,7 @@ int ocre_initialize(const struct ocre_runtime_vtable *const vtable[]); * Creates a new Ocre Context with the specified working directory. * * Creating multiple Ocre Contexts is allowed, but each context must have its own working directory. Using the same - * working directory for multiple contexts is considered an error and results in undefined behavior. + * working directory for multiple contexts will result in an error. * * @param workdir The working directory for the new context. Absolute path, NULL for default. * diff --git a/src/ocre/ocre.c b/src/ocre/ocre.c index ff305f24..3929a9c4 100644 --- a/src/ocre/ocre.c +++ b/src/ocre/ocre.c @@ -203,59 +203,86 @@ static int ocre_destroy_context_locked(struct ocre_context *context) struct ocre_context *ocre_create_context(const char *workdir) { int rc; + struct context_node *add = NULL; + struct context_node *elt; + struct ocre_context *context = NULL; if (!workdir) { workdir = CONFIG_OCRE_DEFAULT_WORKING_DIRECTORY; LOG_INF("Using default working directory: %s", workdir); } - // TODO check if working directory is already taken + rc = pthread_mutex_lock(&contexts_mutex); + if (rc) { + LOG_ERR("Failed to lock mutex: rc=%d", rc); + return NULL; + } - struct context_node *node = malloc(sizeof(struct context_node)); - if (!node) { + LL_FOREACH(contexts, elt) + { + if (!strcmp(elt->working_directory, workdir)) { + LOG_INF("Context already exists for working directory: %s", workdir); + goto error; + } + } + + add = malloc(sizeof(struct context_node)); + if (!add) { LOG_ERR("Failed to allocate memory for context node: errno=%d", errno); - return NULL; + goto error; } - memset(node, 0, sizeof(struct context_node)); + memset(add, 0, sizeof(struct context_node)); - node->working_directory = strdup(workdir); - if (!node->working_directory) { + add->working_directory = strdup(workdir); + if (!add->working_directory) { LOG_ERR("Failed to allocate memory for working directory: errno=%d", errno); goto error; } /* Initialize working directory */ - rc = populate_context_workdir(node->working_directory); + rc = populate_context_workdir(add->working_directory); if (rc) { LOG_ERR("Failed to populate Ocre working directory: rc=%d", rc); goto error; } #if CONFIG_OCRE_FILESYSTEM - delete_container_workdirs(node->working_directory); + delete_container_workdirs(add->working_directory); #endif - node->context = ocre_context_create(node->working_directory); - if (!node->context) { - LOG_ERR("Failed to create Ocre context"); - goto error; - } + context = ocre_context_create(add->working_directory); + if (!context) { + LOG_ERR("Failed to create Ocre context"); + goto error; + } + + add->context = context; + + LL_APPEND(contexts, add); - return node->context; + goto finish; error: - free(node->working_directory); + if (add) { + free(add->working_directory); + } - free(node); + free(add); - return NULL; +finish: + rc = pthread_mutex_unlock(&contexts_mutex); + if (rc) { + LOG_ERR("Failed to unlock mutex: rc=%d", rc); + } + + return context; }; int ocre_destroy_context(struct ocre_context *context) { - int rc = -1; + int rc = -1; if (!context) { LOG_ERR("Invalid context"); @@ -366,10 +393,10 @@ const struct ocre_runtime_vtable *ocre_get_runtime(const char *name) void ocre_deinitialize(void) { - struct context_node *c_node; - struct runtime_node *r_elt, *r_tmp; + struct context_node *c_node; + struct runtime_node *r_elt, *r_tmp; - LL_FOREACH(contexts, c_node) + LL_FOREACH(contexts, c_node) { if (ocre_destroy_context_locked(c_node->context)) { LOG_ERR("Failed to destroy context %p", c_node->context); From f011548d4c38950653c93480943fb09574ac40bc Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Fri, 19 Dec 2025 01:03:05 +0100 Subject: [PATCH 180/234] feat(ocre): refuse to registers runtimes with same name We check if this runtime name is already registered, and if so, we return error. Signed-off-by: Marco Casaroli --- src/ocre/ocre.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/src/ocre/ocre.c b/src/ocre/ocre.c index 3929a9c4..88639313 100644 --- a/src/ocre/ocre.c +++ b/src/ocre/ocre.c @@ -198,6 +198,8 @@ static int ocre_destroy_context_locked(struct ocre_context *context) return 0; } } + + return -1; } struct ocre_context *ocre_create_context(const char *workdir) @@ -341,14 +343,23 @@ int ocre_initialize(const struct ocre_runtime_vtable *const vtable[]) if (vtable) { for (int i = 0; vtable[i] != NULL; i++) { + struct runtime_node *elt; + LL_FOREACH(runtimes, elt) + { + if (!strcmp(elt->runtime->runtime_name, vtable[i]->runtime_name)) { + LOG_ERR("Runtime '%s' already registered", vtable[i]->runtime_name); + goto error; + } + } + struct runtime_node *add = malloc(sizeof(struct runtime_node)); if (!add) { LOG_ERR("Failed to allocate memory for runtime node"); - return -1; + goto error; } memset(add, 0, sizeof(struct runtime_node)); - add->runtime = (const struct ocre_runtime_vtable *)&vtable[i]; + add->runtime = vtable[i]; LL_APPEND(runtimes, add); @@ -356,14 +367,15 @@ int ocre_initialize(const struct ocre_runtime_vtable *const vtable[]) } } - /* Initialize runtimes in the list */ + /* Initialize all runtimes in the list */ - struct runtime_node *elt; + struct runtime_node *elt, *tmp; LL_FOREACH(runtimes, elt) { if (elt->runtime->init && elt->runtime->init()) { LOG_INF("Failed to initialize '%s'", elt->runtime->runtime_name); + ocre_deinitialize(); return -1; } @@ -371,6 +383,16 @@ int ocre_initialize(const struct ocre_runtime_vtable *const vtable[]) } return 0; + +error: + LL_FOREACH_SAFE(runtimes, elt, tmp) + { + LL_DELETE(runtimes, elt); + + free(elt); + } + + return -1; } const struct ocre_runtime_vtable *ocre_get_runtime(const char *name) @@ -396,6 +418,8 @@ void ocre_deinitialize(void) struct context_node *c_node; struct runtime_node *r_elt, *r_tmp; + /* Destroy all contexts */ + LL_FOREACH(contexts, c_node) { if (ocre_destroy_context_locked(c_node->context)) { @@ -403,6 +427,8 @@ void ocre_deinitialize(void) } } + /* Deinitialize all runtimes */ + LL_FOREACH_SAFE(runtimes, r_elt, r_tmp) { if (r_elt->runtime->deinit && r_elt->runtime->deinit()) { From b4542f2e2277cd4814740fdba9c3573ea32d057f Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Fri, 19 Dec 2025 03:06:09 +0100 Subject: [PATCH 181/234] fix(context,ocre): use safe iterator for cleanup Since we are deleting elements from the the vector, we should use the safe functions. Signed-off-by: Marco Casaroli --- src/ocre/context.c | 4 ++-- src/ocre/ocre.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ocre/context.c b/src/ocre/context.c index 6287f772..68132058 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -125,7 +125,7 @@ struct ocre_container *ocre_context_get_container_by_id_locked(const struct ocre int ocre_context_destroy(struct ocre_context *context) { - struct container_node *node; + struct container_node *node, *tmp; /* Send kill event to all containers */ @@ -143,7 +143,7 @@ int ocre_context_destroy(struct ocre_context *context) /* Remove all containers */ - LL_FOREACH(context->containers, node) + LL_FOREACH_SAFE(context->containers, node, tmp) { ocre_context_remove_container_locked(context, node->container); } diff --git a/src/ocre/ocre.c b/src/ocre/ocre.c index 88639313..c3db0b0c 100644 --- a/src/ocre/ocre.c +++ b/src/ocre/ocre.c @@ -415,12 +415,12 @@ const struct ocre_runtime_vtable *ocre_get_runtime(const char *name) void ocre_deinitialize(void) { - struct context_node *c_node; + struct context_node *c_node, *c_tmp; struct runtime_node *r_elt, *r_tmp; /* Destroy all contexts */ - LL_FOREACH(contexts, c_node) + LL_FOREACH_SAFE(contexts, c_node, c_tmp) { if (ocre_destroy_context_locked(c_node->context)) { LOG_ERR("Failed to destroy context %p", c_node->context); From bd719797dd7d7667880c77d62d633327db02d97f Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Fri, 19 Dec 2025 03:06:47 +0100 Subject: [PATCH 182/234] fix(context): improve error handling Signed-off-by: Marco Casaroli --- src/ocre/context.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/ocre/context.c b/src/ocre/context.c index 68132058..557358a4 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -171,13 +171,18 @@ struct ocre_container *ocre_context_create_container(struct ocre_context *contex char random_id[RANDOM_ID_LEN]; int rc; + if (!context) { + LOG_ERR("Invalid context"); + return NULL; + } + /* Check if the provided container ID is valid */ if (container_id && !ocre_is_valid_id(container_id)) { LOG_ERR("Invalid characters in container ID '%s'. Valid are [a-z0-9_-.] (lowercase alphanumeric) and " "cannot start with '.'", container_id); - goto error; + return NULL; } /* Check if the provided image ID is valid */ @@ -186,7 +191,7 @@ struct ocre_container *ocre_context_create_container(struct ocre_context *contex LOG_ERR("Invalid characters in image ID '%s'. Valid are [a-z0-9_-.] (lowercase alphanumeric) and " "cannot start with '.'", image); - goto error; + return NULL; } rc = pthread_mutex_lock(&context->mutex); @@ -364,6 +369,10 @@ int ocre_context_get_num_containers(struct ocre_context *context) const char *ocre_context_get_working_directory(const struct ocre_context *context) { + if (!context) { + return NULL; + } + /* We never change this, no need to lock */ return context->working_directory; From 3c34d56ac8713c85b7f6273ab13fe634214fef95 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Fri, 19 Dec 2025 10:37:29 +0100 Subject: [PATCH 183/234] fix(wamr): dir_map_list memory leak We properly free this after we have called the runtime. We use realloc properly to be able to no leak the intermediate dir_map_lists. Signed-off-by: Marco Casaroli --- src/runtime/wamr/wamr.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/runtime/wamr/wamr.c b/src/runtime/wamr/wamr.c index 47693dc1..ae442f7c 100644 --- a/src/runtime/wamr/wamr.c +++ b/src/runtime/wamr/wamr.c @@ -173,6 +173,7 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s { struct wamr_context *context = NULL; char **dir_map_list = NULL; + char **new_dir_map_list = NULL; size_t dir_map_list_len = 0; if (!img_path) { @@ -278,7 +279,7 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s #endif #if CONFIG_OCRE_FILESYSTEM else if (!strcmp(*cap, "filesystem") && workdir) { - dir_map_list = malloc(sizeof(char *)); + dir_map_list = malloc((dir_map_list_len + 2) * sizeof(char *)); if (!dir_map_list) { LOG_ERR("Failed to allocate memory for dir_map_list"); goto error; @@ -286,17 +287,19 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s memset(dir_map_list, 0, sizeof(char *)); - dir_map_list[0] = malloc(strlen("/::") + strlen(workdir) + 1); - if (!dir_map_list[0]) { + dir_map_list[dir_map_list_len] = malloc(strlen("/::") + strlen(workdir) + 1); + if (!dir_map_list[dir_map_list_len]) { LOG_ERR("Failed to allocate memory for dir_map_list[0]"); free(dir_map_list); goto error; } - sprintf(dir_map_list[0], "/::%s", workdir); + sprintf(dir_map_list[dir_map_list_len], "/::%s", workdir); dir_map_list_len++; + dir_map_list[dir_map_list_len] = NULL; + LOG_INF("Filesystem capability enabled"); } #endif @@ -307,6 +310,14 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s for (const char **mount = mounts; mount && *mount; mount++) { /* Need to insert the extra ':' */ + new_dir_map_list = realloc(dir_map_list, (dir_map_list_len + 2) * sizeof(char *)); + if (!new_dir_map_list) { + LOG_ERR("Failed to allocate memory for dir_map_list"); + goto error; + } + + dir_map_list = new_dir_map_list; + dir_map_list[dir_map_list_len] = malloc(strlen(*mount) + 2); if (!dir_map_list[dir_map_list_len]) { LOG_ERR("Failed to allocate memory for dir_map_list[%zu]", dir_map_list_len); @@ -332,6 +343,9 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s LOG_INF("Enabled mount: %s", dir_map_list[dir_map_list_len]); dir_map_list_len++; + + /* Add the NULL */ + dir_map_list[dir_map_list_len] = NULL; } wasm_runtime_set_wasi_args(context->module, NULL, 0, (const char **)dir_map_list, dir_map_list_len, envp, envn, @@ -372,6 +386,12 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s } } + for (char **dir_map = dir_map_list; dir_map && *dir_map; dir_map++) { + free(*dir_map); + } + + free(dir_map_list); + return context; error_instance: From 8015413efc63b0b0456f081fee6cd88feb600621 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Fri, 19 Dec 2025 14:17:50 +0100 Subject: [PATCH 184/234] fix(container, wamr): race condition on container_kill There was a race condition, where if we called ocre_container_kill just after ocre_container_start (detached) but before the thread gets created and cleared the WASM exception. In this scenario, the kill command would be processed before the cleaning of the exception, and ocre sets the status to stopped but still the container starts later, yielding wrong behavior if the containers is requested to be killed fast enough. We change the semantics of the runtime engine interface, so we pass a conditional variable that must be signalled by this the thread_execute function, allowing the start function to return just after the runtime engine can handle the kill command. The documentation about the vtable will be updated regarding this expectation. Signed-off-by: Marco Casaroli --- src/ocre/container.c | 65 ++++++++++++++++------- src/runtime/include/ocre/runtime/vtable.h | 10 ++-- src/runtime/wamr/wamr.c | 22 ++++++-- 3 files changed, 70 insertions(+), 27 deletions(-) diff --git a/src/ocre/container.c b/src/ocre/container.c index 01b7222c..c68163e5 100644 --- a/src/ocre/container.c +++ b/src/ocre/container.c @@ -22,7 +22,8 @@ struct ocre_container { bool detached; ocre_container_status_t status; pthread_mutex_t mutex; - pthread_cond_t cond; + pthread_cond_t cond_start; + pthread_cond_t cond_stop; void *runtime_context; pthread_t thread; pthread_attr_t attr; @@ -33,8 +34,9 @@ struct ocre_container { }; struct container_thread_params { - int (*func)(void *); + int (*func)(void *, pthread_cond_t *); struct ocre_container *container; + pthread_cond_t *cond; }; static void *container_thread(void *arg) @@ -42,23 +44,22 @@ static void *container_thread(void *arg) int rc; struct container_thread_params *params = arg; struct ocre_container *container = params->container; - int (*func)(void *) = params->func; - - free(params); /* Run the container */ - int result = func(container->runtime_context); + int result = params->func(container->runtime_context, params->cond); /* Exited */ + free(params); + rc = pthread_mutex_lock(&container->mutex); if (rc) { LOG_ERR("Failed to lock mutex: rc=%d", rc); return NULL; } - /* Here is the **only** place where we should set the status to exited */ + /* Here is the **only** place where we should set the status to EXITED */ container->status = OCRE_CONTAINER_STATUS_EXITED; container->exit_code = result; @@ -67,7 +68,7 @@ static void *container_thread(void *arg) /* Notify any waiting threads */ - rc = pthread_cond_broadcast(&container->cond); + rc = pthread_cond_broadcast(&container->cond_stop); if (rc) { LOG_WRN("Failed to broadcast conditional variable: rc=%d", rc); } @@ -225,9 +226,15 @@ struct ocre_container *ocre_container_create(const char *img_path, const char *w goto error_free; } - rc = pthread_cond_init(&container->cond, NULL); + rc = pthread_cond_init(&container->cond_stop, NULL); if (rc) { - LOG_ERR("Failed to initialize conditional variable: rc=%d", rc); + LOG_ERR("Failed to initialize stop conditional variable: rc=%d", rc); + goto error_mutex; + } + + rc = pthread_cond_init(&container->cond_start, NULL); + if (rc) { + LOG_ERR("Failed to initialize start conditional variable: rc=%d", rc); goto error_mutex; } @@ -248,9 +255,14 @@ struct ocre_container *ocre_container_create(const char *img_path, const char *w return container; error_cond: - rc = pthread_cond_destroy(&container->cond); + rc = pthread_cond_destroy(&container->cond_start); + if (rc) { + LOG_ERR("Failed to deinitialize start conditional variable: rc=%d", rc); + } + + rc = pthread_cond_destroy(&container->cond_stop); if (rc) { - LOG_ERR("Failed to deinitialize conditional variable: rc=%d", rc); + LOG_ERR("Failed to deinitialize stop conditional variable: rc=%d", rc); } error_mutex: @@ -292,9 +304,14 @@ int ocre_container_destroy(struct ocre_container *container) LOG_ERR("Failed to deinitialize mutex: rc=%d", rc); } - rc = pthread_cond_destroy(&container->cond); + rc = pthread_cond_destroy(&container->cond_start); if (rc) { - LOG_ERR("Failed to deinitialize conditional variable: rc=%d", rc); + LOG_ERR("Failed to deinitialize start conditional variable: rc=%d", rc); + } + + rc = pthread_cond_destroy(&container->cond_stop); + if (rc) { + LOG_ERR("Failed to deinitialize stop conditional variable: rc=%d", rc); } string_array_free(container->argv); @@ -353,6 +370,7 @@ int ocre_container_start(struct ocre_container *container) memset(params, 0, sizeof(struct container_thread_params)); params->container = container; params->func = container->runtime->thread_execute; + params->cond = &container->cond_start; container->status = OCRE_CONTAINER_STATUS_RUNNING; rc = pthread_create(&container->thread, &container->attr, container_thread, params); @@ -361,6 +379,14 @@ int ocre_container_start(struct ocre_container *container) goto error_params; } + LOG_INF("Waiting for container '%s' to start", container->id); + + rc = pthread_cond_wait(&container->cond_start, &container->mutex); + if (rc) { + LOG_ERR("Failed to wait on start conditional variable: rc=%d", rc); + goto error_status; + } + LOG_INF("Started container '%s' on runtime '%s'", container->id, container->runtime->runtime_name); rc = pthread_mutex_unlock(&container->mutex); @@ -370,7 +396,8 @@ int ocre_container_start(struct ocre_container *container) } if (!container->detached) { - /* this will block until the container thread exits */ + /* This will block until the container thread exits */ + if (ocre_container_wait(container, NULL)) { LOG_ERR("Failed to wait for container '%s'", container->id); return -1; @@ -479,10 +506,10 @@ int ocre_container_kill(struct ocre_container *container) goto unlock_mutex; } - LOG_INF("Sending kill signal to container '%s'", container->id); - ret = container->runtime->kill(container->runtime_context); + LOG_INF("Sent kill signal to container '%s'", container->id); + unlock_mutex: rc = pthread_mutex_unlock(&container->mutex); if (rc) { @@ -605,9 +632,9 @@ int ocre_container_wait(struct ocre_container *container, int *status) if (container->status == OCRE_CONTAINER_STATUS_RUNNING) { LOG_INF("Container '%s' is running", container->id); - rc = pthread_cond_wait(&container->cond, &container->mutex); + rc = pthread_cond_wait(&container->cond_stop, &container->mutex); if (rc) { - LOG_ERR("Failed to wait on conditional variable: rc=%d", rc); + LOG_ERR("Failed to wait on stop conditional variable: rc=%d", rc); goto unlock_mutex; } } diff --git a/src/runtime/include/ocre/runtime/vtable.h b/src/runtime/include/ocre/runtime/vtable.h index 31c168b4..56e8ae7c 100644 --- a/src/runtime/include/ocre/runtime/vtable.h +++ b/src/runtime/include/ocre/runtime/vtable.h @@ -2,6 +2,7 @@ #define OCRE_RUNTIME_VTABLE_H #include +#include /** * @brief Runtime Engine Virtual Table @@ -85,12 +86,13 @@ struct ocre_runtime_vtable { * This function is called inside a thread when the container is started. It should execute the container's main * function, block and eventually return the exit code. * - * @param arg Pointer to the argument passed to the thread - * @return Pointer to the thread context on success, NULL on failure + * @param runtime_context Pointer to the runtime context returned by create + * @param cond Pointer to the conditional variable to signal when the instance is ready to be killed + * + * @return status code of the execution: 0 on success, non-zero on failure */ - // TODO: ARG???? - int (*thread_execute)(void *arg); + int (*thread_execute)(void *runtime_context, pthread_cond_t *cond); /** * @brief Stop a runtime instance diff --git a/src/runtime/wamr/wamr.c b/src/runtime/wamr/wamr.c index ae442f7c..2405d2bb 100644 --- a/src/runtime/wamr/wamr.c +++ b/src/runtime/wamr/wamr.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -37,7 +38,7 @@ struct wamr_context { bool uses_ocre_api; }; -static int instance_execute(void *runtime_context) +static int instance_execute(void *runtime_context, pthread_cond_t *cond) { struct wamr_context *context = runtime_context; wasm_module_inst_t module_inst = context->module_inst; @@ -46,6 +47,17 @@ static int instance_execute(void *runtime_context) wasm_runtime_clear_exception(module_inst); + /* Notify the starting waiter that we are ready + * We should notify only after we are ready to process the kill call. + * In WAMR, this is managed by the exception message, so we are good if we just cleared the exception. + */ + + int rc = pthread_cond_signal(cond); + if (rc) { + LOG_WRN("Failed to signal start conditional variable: rc=%d", rc); + return -1; + } + /* Execute main function */ const char *exception = NULL; @@ -69,16 +81,18 @@ static int instance_execute(void *runtime_context) LOG_INF("Context %p completed successfully", context); - return wasm_runtime_get_wasi_exit_code(context->module_inst); + int exit_code = wasm_runtime_get_wasi_exit_code(context->module_inst); + + return exit_code; } -static int instance_thread_execute(void *arg) +static int instance_thread_execute(void *arg, pthread_cond_t *cond) { struct wamr_context *context = arg; wasm_runtime_init_thread_env(); - int ret = instance_execute(context); + int ret = instance_execute(context, cond); wasm_runtime_destroy_thread_env(); From 4612f174b68b4d2407ddf99d98be52b880b5a9fe Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Fri, 19 Dec 2025 15:12:59 +0100 Subject: [PATCH 185/234] chore: add license banners Signed-off-by: Marco Casaroli --- .github/workflows/devcontainer-linux.yml | 5 +++++ .github/workflows/devcontainer-zephyr.yml | 5 +++++ .github/workflows/linux.yml | 5 +++++ .github/workflows/main.yml | 5 +++++ .github/workflows/zephyr.yml | 5 +++++ CMakeLists.txt | 5 +++++ cmake/state_information.cmake | 5 +++++ cmake/wamr.cmake | 5 +++++ src/ocre/CMakeLists.txt | 5 +++++ src/ocre/container.c | 7 +++++++ src/ocre/container.h | 9 ++++++++- src/ocre/context.c | 7 +++++++ src/ocre/context.h | 7 +++++++ src/ocre/include/ocre/ocre.h | 7 +++++++ src/ocre/ocre.c | 7 +++++++ src/ocre/ocre.h | 7 +++++++ src/ocre/util/rm_rf.c | 7 +++++++ src/ocre/util/rm_rf.h | 7 +++++++ src/ocre/util/string_array.c | 7 +++++++ src/ocre/util/string_array.h | 7 +++++++ src/ocre/util/unique_random_id.c | 7 +++++++ src/ocre/util/unique_random_id.h | 7 +++++++ src/ocre/version.h | 7 +++++++ src/runtime/CMakeLists.txt | 5 +++++ src/runtime/include/ocre/runtime/vtable.h | 7 +++++++ src/runtime/wamr/CMakeLists.txt | 5 +++++ src/runtime/wamr/include/ocre/runtime/wamr/wamr.h | 7 +++++++ src/runtime/wamr/ocre_api/CMakeLists.txt | 5 +++++ src/runtime/wamr/wamr.c | 7 +++++++ src/samples/demo/demo_containers.cmake | 5 +++++ src/samples/demo/main.c | 7 +++++++ src/samples/demo/posix/CMakeLists.txt | 5 +++++ src/samples/demo/zephyr/CMakeLists.txt | 5 +++++ src/samples/demo/zephyr/boards/native_sim_64.conf | 5 +++++ .../demo/zephyr/boards/pico_plus2_rp2350b_m33.conf | 5 +++++ .../demo/zephyr/boards/pico_plus2_rp2350b_m33_w.conf | 5 +++++ src/samples/demo/zephyr/prj.conf | 5 +++++ src/samples/mini/input_file.cmake | 5 +++++ src/samples/mini/main.c | 7 +++++++ src/samples/mini/posix/CMakeLists.txt | 5 +++++ src/samples/mini/zephyr/CMakeLists.txt | 5 +++++ src/samples/mini/zephyr/boards/native_sim_64.conf | 5 +++++ .../mini/zephyr/boards/pico_plus2_rp2350b_m33.conf | 5 +++++ .../mini/zephyr/boards/pico_plus2_rp2350b_m33_w.conf | 5 +++++ src/samples/mini/zephyr/prj.conf | 5 +++++ src/samples/static_checks/posix/CMakeLists.txt | 5 +++++ src/samples/static_checks/posix/download_file.c | 7 +++++++ src/samples/static_checks/posix/ocre.c | 7 +++++++ src/samples/supervisor/zephyr/CMakeLists.txt | 5 +++++ src/samples/supervisor/zephyr/boards/b_u585i_iot02a.conf | 5 +++++ .../supervisor/zephyr/boards/b_u585i_iot02a.overlay | 7 +++++++ src/samples/supervisor/zephyr/boards/native_sim_64.conf | 5 +++++ .../supervisor/zephyr/boards/native_sim_64.overlay | 7 +++++++ .../supervisor/zephyr/boards/pico_plus2_rp2350b_m33.conf | 5 +++++ .../zephyr/boards/pico_plus2_rp2350b_m33.overlay | 7 +++++++ .../zephyr/boards/pico_plus2_rp2350b_m33_w.conf | 5 +++++ .../zephyr/boards/pico_plus2_rp2350b_m33_w.overlay | 7 +++++++ .../zephyr/boards/pico_plus2_rp2350b_m33_w_mcuboot.conf | 5 +++++ src/samples/supervisor/zephyr/download_file.c | 7 +++++++ src/samples/supervisor/zephyr/fstab.overlay | 7 +++++++ src/samples/supervisor/zephyr/prj.conf | 5 +++++ src/samples/supervisor/zephyr/service.c | 7 +++++++ src/samples/supervisor/zephyr/shell.c | 7 +++++++ src/shell/CMakeLists.txt | 5 +++++ src/shell/command.h | 7 +++++++ src/shell/container.c | 7 +++++++ src/shell/container.h | 7 +++++++ src/shell/container/create.c | 7 +++++++ src/shell/container/create.h | 7 +++++++ src/shell/container/kill.c | 7 +++++++ src/shell/container/kill.h | 7 +++++++ src/shell/container/pause.h | 7 +++++++ src/shell/container/ps.c | 7 +++++++ src/shell/container/ps.h | 7 +++++++ src/shell/container/rm.c | 7 +++++++ src/shell/container/rm.h | 7 +++++++ src/shell/container/start.c | 7 +++++++ src/shell/container/start.h | 7 +++++++ src/shell/container/stop.c | 7 +++++++ src/shell/container/stop.h | 7 +++++++ src/shell/container/unpause.c | 7 +++++++ src/shell/container/unpause.h | 7 +++++++ src/shell/container/wait.c | 7 +++++++ src/shell/container/wait.h | 7 +++++++ src/shell/image.c | 7 +++++++ src/shell/image.h | 7 +++++++ src/shell/image/ls.c | 7 +++++++ src/shell/image/ls.h | 7 +++++++ src/shell/image/pull.c | 7 +++++++ src/shell/image/pull.h | 7 +++++++ src/shell/image/rm.c | 7 +++++++ src/shell/image/rm.h | 7 +++++++ src/shell/image/sha256_file.c | 7 +++++++ src/shell/image/sha256_file.h | 7 +++++++ src/shell/include/ocre/shell/shell.h | 7 +++++++ src/shell/shell.c | 7 +++++++ zephyr/CMakeLists.txt | 5 +++++ zephyr/Kconfig | 5 +++++ zephyr/module.yml | 5 +++++ zephyr/storage_partition.cmake | 5 +++++ zephyr/wamr.cmake | 5 +++++ 101 files changed, 628 insertions(+), 1 deletion(-) diff --git a/.github/workflows/devcontainer-linux.yml b/.github/workflows/devcontainer-linux.yml index 18cc692b..1cc809c0 100644 --- a/.github/workflows/devcontainer-linux.yml +++ b/.github/workflows/devcontainer-linux.yml @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + name: Linux devcontainer on: diff --git a/.github/workflows/devcontainer-zephyr.yml b/.github/workflows/devcontainer-zephyr.yml index 0066b179..ed5bd4a2 100644 --- a/.github/workflows/devcontainer-zephyr.yml +++ b/.github/workflows/devcontainer-zephyr.yml @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + name: Zephyr devcontainer on: diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index e00a5a37..e9941c44 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + name: Linux on: diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6b872b16..9d199bf4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + name: Main on: diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index a8feadc7..c87a43a1 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + name: Zephyr on: diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f8a4b95..5398cfaa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + cmake_minimum_required(VERSION 3.20.0) project(ocre LANGUAGES C ASM) diff --git a/cmake/state_information.cmake b/cmake/state_information.cmake index 0a18f5f0..8f5a3574 100644 --- a/cmake/state_information.cmake +++ b/cmake/state_information.cmake @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + cmake_minimum_required(VERSION 3.20.0) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/var/lib/ocre/images) diff --git a/cmake/wamr.cmake b/cmake/wamr.cmake index c3b30739..33cea916 100644 --- a/cmake/wamr.cmake +++ b/cmake/wamr.cmake @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + set (WAMR_BUILD_INTERP 1) set (WAMR_BUILD_FAST_INTERP 0) set (WAMR_BUILD_AOT 1) diff --git a/src/ocre/CMakeLists.txt b/src/ocre/CMakeLists.txt index 67776081..e711baa9 100644 --- a/src/ocre/CMakeLists.txt +++ b/src/ocre/CMakeLists.txt @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + # Check if we are in a git repository execute_process( COMMAND git rev-parse --git-dir diff --git a/src/ocre/container.c b/src/ocre/container.c index c68163e5..a4707ad1 100644 --- a/src/ocre/container.c +++ b/src/ocre/container.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include #include diff --git a/src/ocre/container.h b/src/ocre/container.h index 4c688b08..d0bde692 100644 --- a/src/ocre/container.h +++ b/src/ocre/container.h @@ -1,4 +1,11 @@ -#include +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + + #include struct ocre_container; diff --git a/src/ocre/context.c b/src/ocre/context.c index 557358a4..a863e7c3 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include #include diff --git a/src/ocre/context.h b/src/ocre/context.h index db8eed0c..aeba5c3e 100644 --- a/src/ocre/context.h +++ b/src/ocre/context.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + struct ocre_context; struct ocre_context *ocre_context_create(const char *workdir); diff --git a/src/ocre/include/ocre/ocre.h b/src/ocre/include/ocre/ocre.h index 0acecaa8..a492c674 100644 --- a/src/ocre/include/ocre/ocre.h +++ b/src/ocre/include/ocre/ocre.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + /** * @file ocre.h * diff --git a/src/ocre/ocre.c b/src/ocre/ocre.c index c3db0b0c..4bd6cb6e 100644 --- a/src/ocre/ocre.c +++ b/src/ocre/ocre.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include #include diff --git a/src/ocre/ocre.h b/src/ocre/ocre.h index d47ac907..ce695846 100644 --- a/src/ocre/ocre.h +++ b/src/ocre/ocre.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include const struct ocre_runtime_vtable *ocre_get_runtime(const char *name); diff --git a/src/ocre/util/rm_rf.c b/src/ocre/util/rm_rf.c index 53045a77..5283a399 100644 --- a/src/ocre/util/rm_rf.c +++ b/src/ocre/util/rm_rf.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include #include diff --git a/src/ocre/util/rm_rf.h b/src/ocre/util/rm_rf.h index fd3b9440..91f70dd7 100644 --- a/src/ocre/util/rm_rf.h +++ b/src/ocre/util/rm_rf.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #ifndef RM_RF_H #define RM_RF_H diff --git a/src/ocre/util/string_array.c b/src/ocre/util/string_array.c index ef6168b9..89bcd808 100644 --- a/src/ocre/util/string_array.c +++ b/src/ocre/util/string_array.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include #include diff --git a/src/ocre/util/string_array.h b/src/ocre/util/string_array.h index d6126fbf..a129911c 100644 --- a/src/ocre/util/string_array.h +++ b/src/ocre/util/string_array.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include /* returns the size of a string array including the NULL termination diff --git a/src/ocre/util/unique_random_id.c b/src/ocre/util/unique_random_id.c index 2fd4eaa8..7e1ba775 100644 --- a/src/ocre/util/unique_random_id.c +++ b/src/ocre/util/unique_random_id.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include #include diff --git a/src/ocre/util/unique_random_id.h b/src/ocre/util/unique_random_id.h index ad771374..c05709e7 100644 --- a/src/ocre/util/unique_random_id.h +++ b/src/ocre/util/unique_random_id.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include diff --git a/src/ocre/version.h b/src/ocre/version.h index 09772e27..6e1ad644 100644 --- a/src/ocre/version.h +++ b/src/ocre/version.h @@ -1 +1,8 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #define OCRE_VERSION_STRING "0.7.0" diff --git a/src/runtime/CMakeLists.txt b/src/runtime/CMakeLists.txt index d5d0dc57..35a2b740 100644 --- a/src/runtime/CMakeLists.txt +++ b/src/runtime/CMakeLists.txt @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + cmake_minimum_required(VERSION 3.20) add_library(OcreRuntime diff --git a/src/runtime/include/ocre/runtime/vtable.h b/src/runtime/include/ocre/runtime/vtable.h index 56e8ae7c..4d0f15d9 100644 --- a/src/runtime/include/ocre/runtime/vtable.h +++ b/src/runtime/include/ocre/runtime/vtable.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #ifndef OCRE_RUNTIME_VTABLE_H #define OCRE_RUNTIME_VTABLE_H diff --git a/src/runtime/wamr/CMakeLists.txt b/src/runtime/wamr/CMakeLists.txt index 6e54b27e..25286ba4 100644 --- a/src/runtime/wamr/CMakeLists.txt +++ b/src/runtime/wamr/CMakeLists.txt @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + add_library(OcreRuntimeWamr) target_sources(OcreRuntimeWamr diff --git a/src/runtime/wamr/include/ocre/runtime/wamr/wamr.h b/src/runtime/wamr/include/ocre/runtime/wamr/wamr.h index b35e45b9..bca970f6 100644 --- a/src/runtime/wamr/include/ocre/runtime/wamr/wamr.h +++ b/src/runtime/wamr/include/ocre/runtime/wamr/wamr.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #ifndef OCRE_RUNTIME_WAMR_H #define OCRE_RUNTIME_WAMR_H diff --git a/src/runtime/wamr/ocre_api/CMakeLists.txt b/src/runtime/wamr/ocre_api/CMakeLists.txt index e787511a..0d794c85 100644 --- a/src/runtime/wamr/ocre_api/CMakeLists.txt +++ b/src/runtime/wamr/ocre_api/CMakeLists.txt @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + add_library(OcreRuntimeAPI) target_sources(OcreRuntimeAPI diff --git a/src/runtime/wamr/wamr.c b/src/runtime/wamr/wamr.c index 2405d2bb..7d7525ec 100644 --- a/src/runtime/wamr/wamr.c +++ b/src/runtime/wamr/wamr.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include #include diff --git a/src/samples/demo/demo_containers.cmake b/src/samples/demo/demo_containers.cmake index 938d1a03..da5655c6 100644 --- a/src/samples/demo/demo_containers.cmake +++ b/src/samples/demo/demo_containers.cmake @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + list(APPEND OCRE_SDK_PRELOADED_IMAGES "hello-world.wasm" "blinky.wasm" diff --git a/src/samples/demo/main.c b/src/samples/demo/main.c index 71cb43ed..06e3edbb 100644 --- a/src/samples/demo/main.c +++ b/src/samples/demo/main.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include diff --git a/src/samples/demo/posix/CMakeLists.txt b/src/samples/demo/posix/CMakeLists.txt index 3129b750..619574de 100644 --- a/src/samples/demo/posix/CMakeLists.txt +++ b/src/samples/demo/posix/CMakeLists.txt @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + cmake_minimum_required(VERSION 3.20.0) project (ocre_sample_demo) diff --git a/src/samples/demo/zephyr/CMakeLists.txt b/src/samples/demo/zephyr/CMakeLists.txt index 4f07039b..6104ea45 100644 --- a/src/samples/demo/zephyr/CMakeLists.txt +++ b/src/samples/demo/zephyr/CMakeLists.txt @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + # This file is to be used to build a zephyr firmware including the ocre demo # automatically uses the ocre module in the parent directory diff --git a/src/samples/demo/zephyr/boards/native_sim_64.conf b/src/samples/demo/zephyr/boards/native_sim_64.conf index 9d6871c3..2205c3f0 100644 --- a/src/samples/demo/zephyr/boards/native_sim_64.conf +++ b/src/samples/demo/zephyr/boards/native_sim_64.conf @@ -1 +1,6 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=10485760 diff --git a/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33.conf b/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33.conf index fd303152..dbf84249 100644 --- a/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33.conf +++ b/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33.conf @@ -1,2 +1,7 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_SHARED_MULTI_HEAP=y diff --git a/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33_w.conf b/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33_w.conf index fd303152..dbf84249 100644 --- a/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33_w.conf +++ b/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33_w.conf @@ -1,2 +1,7 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_SHARED_MULTI_HEAP=y diff --git a/src/samples/demo/zephyr/prj.conf b/src/samples/demo/zephyr/prj.conf index b3c7b01b..d5fe8692 100644 --- a/src/samples/demo/zephyr/prj.conf +++ b/src/samples/demo/zephyr/prj.conf @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + # Logging CONFIG_LOG=y CONFIG_LOG_MODE_MINIMAL=y diff --git a/src/samples/mini/input_file.cmake b/src/samples/mini/input_file.cmake index 38ee210f..a8a95bf7 100644 --- a/src/samples/mini/input_file.cmake +++ b/src/samples/mini/input_file.cmake @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + if(OCRE_INPUT_FILE) message(STATUS "Using user input file: ${OCRE_INPUT_FILE}") else() diff --git a/src/samples/mini/main.c b/src/samples/mini/main.c index 3fe6f693..ad43340b 100644 --- a/src/samples/mini/main.c +++ b/src/samples/mini/main.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include #include diff --git a/src/samples/mini/posix/CMakeLists.txt b/src/samples/mini/posix/CMakeLists.txt index 597131d5..d9d8bee4 100644 --- a/src/samples/mini/posix/CMakeLists.txt +++ b/src/samples/mini/posix/CMakeLists.txt @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + cmake_minimum_required(VERSION 3.20.0) project (ocre_sample_mini) diff --git a/src/samples/mini/zephyr/CMakeLists.txt b/src/samples/mini/zephyr/CMakeLists.txt index 90ca467f..b1bbd02c 100644 --- a/src/samples/mini/zephyr/CMakeLists.txt +++ b/src/samples/mini/zephyr/CMakeLists.txt @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + # This file is to be used to build a zephyr firmware including the ocre demo # automatically uses the ocre module in the parent directory diff --git a/src/samples/mini/zephyr/boards/native_sim_64.conf b/src/samples/mini/zephyr/boards/native_sim_64.conf index 9d6871c3..2205c3f0 100644 --- a/src/samples/mini/zephyr/boards/native_sim_64.conf +++ b/src/samples/mini/zephyr/boards/native_sim_64.conf @@ -1 +1,6 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=10485760 diff --git a/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33.conf b/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33.conf index fd303152..dbf84249 100644 --- a/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33.conf +++ b/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33.conf @@ -1,2 +1,7 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_SHARED_MULTI_HEAP=y diff --git a/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33_w.conf b/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33_w.conf index eebef5c9..d2e7b389 100644 --- a/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33_w.conf +++ b/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33_w.conf @@ -1,2 +1,7 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + CONFIG_TEST_RANDOM_GENERATOR=y #CONFIG_SHARED_MULTI_HEAP=y diff --git a/src/samples/mini/zephyr/prj.conf b/src/samples/mini/zephyr/prj.conf index faa4534c..7a6358e3 100644 --- a/src/samples/mini/zephyr/prj.conf +++ b/src/samples/mini/zephyr/prj.conf @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + # Logging CONFIG_LOG=y CONFIG_LOG_MODE_MINIMAL=y diff --git a/src/samples/static_checks/posix/CMakeLists.txt b/src/samples/static_checks/posix/CMakeLists.txt index 5c1797f1..a0f08a5f 100644 --- a/src/samples/static_checks/posix/CMakeLists.txt +++ b/src/samples/static_checks/posix/CMakeLists.txt @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + cmake_minimum_required(VERSION 3.20.0) project (ocre_cmd) diff --git a/src/samples/static_checks/posix/download_file.c b/src/samples/static_checks/posix/download_file.c index 28b379f9..17400bc8 100644 --- a/src/samples/static_checks/posix/download_file.c +++ b/src/samples/static_checks/posix/download_file.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + int ocre_download_file(const char *url, const char *filepath) { /* Not implemented */ diff --git a/src/samples/static_checks/posix/ocre.c b/src/samples/static_checks/posix/ocre.c index ad4f4595..27c3c03f 100644 --- a/src/samples/static_checks/posix/ocre.c +++ b/src/samples/static_checks/posix/ocre.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include #include diff --git a/src/samples/supervisor/zephyr/CMakeLists.txt b/src/samples/supervisor/zephyr/CMakeLists.txt index 8a981528..cb9094ec 100644 --- a/src/samples/supervisor/zephyr/CMakeLists.txt +++ b/src/samples/supervisor/zephyr/CMakeLists.txt @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + # This file is to be used to build a zephyr firmware including the ocre demo # automatically uses the ocre module in the parent directory diff --git a/src/samples/supervisor/zephyr/boards/b_u585i_iot02a.conf b/src/samples/supervisor/zephyr/boards/b_u585i_iot02a.conf index 4709e32e..8ff854c0 100644 --- a/src/samples/supervisor/zephyr/boards/b_u585i_iot02a.conf +++ b/src/samples/supervisor/zephyr/boards/b_u585i_iot02a.conf @@ -1,2 +1,7 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + CONFIG_STM32_MEMMAP=y CONFIG_OCRE_MERGE_HEX=y diff --git a/src/samples/supervisor/zephyr/boards/b_u585i_iot02a.overlay b/src/samples/supervisor/zephyr/boards/b_u585i_iot02a.overlay index 2804dcf8..5ace830c 100644 --- a/src/samples/supervisor/zephyr/boards/b_u585i_iot02a.overlay +++ b/src/samples/supervisor/zephyr/boards/b_u585i_iot02a.overlay @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include / { diff --git a/src/samples/supervisor/zephyr/boards/native_sim_64.conf b/src/samples/supervisor/zephyr/boards/native_sim_64.conf index 9d6871c3..2205c3f0 100644 --- a/src/samples/supervisor/zephyr/boards/native_sim_64.conf +++ b/src/samples/supervisor/zephyr/boards/native_sim_64.conf @@ -1 +1,6 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=10485760 diff --git a/src/samples/supervisor/zephyr/boards/native_sim_64.overlay b/src/samples/supervisor/zephyr/boards/native_sim_64.overlay index eb2c157d..848942a0 100644 --- a/src/samples/supervisor/zephyr/boards/native_sim_64.overlay +++ b/src/samples/supervisor/zephyr/boards/native_sim_64.overlay @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + &flash0 { reg = < 0x0 DT_SIZE_M(32) >; }; diff --git a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33.conf b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33.conf index fd303152..dbf84249 100644 --- a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33.conf +++ b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33.conf @@ -1,2 +1,7 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_SHARED_MULTI_HEAP=y diff --git a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33.overlay b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33.overlay index 24e3edbb..425ed0d8 100644 --- a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33.overlay +++ b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33.overlay @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + &flash0 { partitions { compatible = "fixed-partitions"; diff --git a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.conf b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.conf index 880b21ea..57a314b6 100644 --- a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.conf +++ b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.conf @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_SHARED_MULTI_HEAP=y CONFIG_WIFI=y diff --git a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay index 24e3edbb..425ed0d8 100644 --- a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay +++ b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + &flash0 { partitions { compatible = "fixed-partitions"; diff --git a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w_mcuboot.conf b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w_mcuboot.conf index 880b21ea..57a314b6 100644 --- a/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w_mcuboot.conf +++ b/src/samples/supervisor/zephyr/boards/pico_plus2_rp2350b_m33_w_mcuboot.conf @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_SHARED_MULTI_HEAP=y CONFIG_WIFI=y diff --git a/src/samples/supervisor/zephyr/download_file.c b/src/samples/supervisor/zephyr/download_file.c index 55690c0e..ba364330 100644 --- a/src/samples/supervisor/zephyr/download_file.c +++ b/src/samples/supervisor/zephyr/download_file.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include #include diff --git a/src/samples/supervisor/zephyr/fstab.overlay b/src/samples/supervisor/zephyr/fstab.overlay index a986be8d..811beedd 100644 --- a/src/samples/supervisor/zephyr/fstab.overlay +++ b/src/samples/supervisor/zephyr/fstab.overlay @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + / { fstab { compatible = "zephyr,fstab"; diff --git a/src/samples/supervisor/zephyr/prj.conf b/src/samples/supervisor/zephyr/prj.conf index 4efa9490..dffe954e 100644 --- a/src/samples/supervisor/zephyr/prj.conf +++ b/src/samples/supervisor/zephyr/prj.conf @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + CONFIG_SHELL=y CONFIG_BOOT_BANNER=y CONFIG_SHELL_PROMPT_UART="ocre:~$ " diff --git a/src/samples/supervisor/zephyr/service.c b/src/samples/supervisor/zephyr/service.c index 5af138aa..38cd7e25 100644 --- a/src/samples/supervisor/zephyr/service.c +++ b/src/samples/supervisor/zephyr/service.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include diff --git a/src/samples/supervisor/zephyr/shell.c b/src/samples/supervisor/zephyr/shell.c index 7f424d68..36363ff4 100644 --- a/src/samples/supervisor/zephyr/shell.c +++ b/src/samples/supervisor/zephyr/shell.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include diff --git a/src/shell/CMakeLists.txt b/src/shell/CMakeLists.txt index 6f26f40b..a073075c 100644 --- a/src/shell/CMakeLists.txt +++ b/src/shell/CMakeLists.txt @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + cmake_minimum_required(VERSION 3.20.0) add_library(OcreShell) diff --git a/src/shell/command.h b/src/shell/command.h index 4059e5b7..8af328a2 100644 --- a/src/shell/command.h +++ b/src/shell/command.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include struct ocre_command { diff --git a/src/shell/container.c b/src/shell/container.c index c49eafdc..cbe52f44 100644 --- a/src/shell/container.c +++ b/src/shell/container.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include diff --git a/src/shell/container.h b/src/shell/container.h index 344a435e..f69cfe09 100644 --- a/src/shell/container.h +++ b/src/shell/container.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include int cmd_container(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/container/create.c b/src/shell/container/create.c index a50f09ad..704f4022 100644 --- a/src/shell/container/create.c +++ b/src/shell/container/create.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include #include diff --git a/src/shell/container/create.h b/src/shell/container/create.h index 9a67f237..57ae0ebc 100644 --- a/src/shell/container/create.h +++ b/src/shell/container/create.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include int cmd_container_create_run(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/container/kill.c b/src/shell/container/kill.c index 0a4ead00..51ed1ac1 100644 --- a/src/shell/container/kill.c +++ b/src/shell/container/kill.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include diff --git a/src/shell/container/kill.h b/src/shell/container/kill.h index f7968a88..c8a3a3c2 100644 --- a/src/shell/container/kill.h +++ b/src/shell/container/kill.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include int cmd_container_kill(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/container/pause.h b/src/shell/container/pause.h index b721a786..808c3649 100644 --- a/src/shell/container/pause.h +++ b/src/shell/container/pause.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include int cmd_container_pause(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/container/ps.c b/src/shell/container/ps.c index fa70d46d..ccf53d32 100644 --- a/src/shell/container/ps.c +++ b/src/shell/container/ps.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include #include diff --git a/src/shell/container/ps.h b/src/shell/container/ps.h index cec6bd23..a63f5fb8 100644 --- a/src/shell/container/ps.h +++ b/src/shell/container/ps.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include int cmd_container_ps(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/container/rm.c b/src/shell/container/rm.c index 43f5a682..1a4bf91e 100644 --- a/src/shell/container/rm.c +++ b/src/shell/container/rm.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include diff --git a/src/shell/container/rm.h b/src/shell/container/rm.h index 07a85823..df057727 100644 --- a/src/shell/container/rm.h +++ b/src/shell/container/rm.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include int cmd_container_rm(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/container/start.c b/src/shell/container/start.c index 05c95274..02706391 100644 --- a/src/shell/container/start.c +++ b/src/shell/container/start.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include diff --git a/src/shell/container/start.h b/src/shell/container/start.h index b001d89e..c843f95d 100644 --- a/src/shell/container/start.h +++ b/src/shell/container/start.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include int cmd_container_start(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/container/stop.c b/src/shell/container/stop.c index 08c5e44f..e683a5fa 100644 --- a/src/shell/container/stop.c +++ b/src/shell/container/stop.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include diff --git a/src/shell/container/stop.h b/src/shell/container/stop.h index 32ccc5c5..89e0c960 100644 --- a/src/shell/container/stop.h +++ b/src/shell/container/stop.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include int cmd_container_stop(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/container/unpause.c b/src/shell/container/unpause.c index fc231085..aca63f13 100644 --- a/src/shell/container/unpause.c +++ b/src/shell/container/unpause.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include diff --git a/src/shell/container/unpause.h b/src/shell/container/unpause.h index ba1346b4..2e54a581 100644 --- a/src/shell/container/unpause.h +++ b/src/shell/container/unpause.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include int cmd_container_unpause(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/container/wait.c b/src/shell/container/wait.c index f9886186..11db581c 100644 --- a/src/shell/container/wait.c +++ b/src/shell/container/wait.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include diff --git a/src/shell/container/wait.h b/src/shell/container/wait.h index 3ca3ebb9..b586ea39 100644 --- a/src/shell/container/wait.h +++ b/src/shell/container/wait.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include int cmd_container_wait(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/image.c b/src/shell/image.c index 540dc1b9..97398def 100644 --- a/src/shell/image.c +++ b/src/shell/image.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include diff --git a/src/shell/image.h b/src/shell/image.h index efa4f924..ba4250f2 100644 --- a/src/shell/image.h +++ b/src/shell/image.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include int cmd_image(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/image/ls.c b/src/shell/image/ls.c index fd76a94c..9a9ced58 100644 --- a/src/shell/image/ls.c +++ b/src/shell/image/ls.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include #include diff --git a/src/shell/image/ls.h b/src/shell/image/ls.h index 85562284..ca6be291 100644 --- a/src/shell/image/ls.h +++ b/src/shell/image/ls.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include int cmd_image_ls(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/image/pull.c b/src/shell/image/pull.c index 3eb780b1..60ece556 100644 --- a/src/shell/image/pull.c +++ b/src/shell/image/pull.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include #include diff --git a/src/shell/image/pull.h b/src/shell/image/pull.h index 85fe88f6..3f5e1bbf 100644 --- a/src/shell/image/pull.h +++ b/src/shell/image/pull.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include int cmd_image_pull(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/image/rm.c b/src/shell/image/rm.c index 865ba8ad..1ad0895a 100644 --- a/src/shell/image/rm.c +++ b/src/shell/image/rm.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include #include diff --git a/src/shell/image/rm.h b/src/shell/image/rm.h index 4ac5d0f1..a5419c05 100644 --- a/src/shell/image/rm.h +++ b/src/shell/image/rm.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include int cmd_image_rm(struct ocre_context *ctx, const char *argv0, int argc, char **argv); diff --git a/src/shell/image/sha256_file.c b/src/shell/image/sha256_file.c index 86ac329a..20033748 100644 --- a/src/shell/image/sha256_file.c +++ b/src/shell/image/sha256_file.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include #include diff --git a/src/shell/image/sha256_file.h b/src/shell/image/sha256_file.h index 891ed6b1..97ae3867 100644 --- a/src/shell/image/sha256_file.h +++ b/src/shell/image/sha256_file.h @@ -1 +1,8 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + int sha256_file(const char *path, char *hash); diff --git a/src/shell/include/ocre/shell/shell.h b/src/shell/include/ocre/shell/shell.h index 84043eeb..6ed95e35 100644 --- a/src/shell/include/ocre/shell/shell.h +++ b/src/shell/include/ocre/shell/shell.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include int ocre_shell(struct ocre_context *ctx, int argc, char *argv[]); diff --git a/src/shell/shell.c b/src/shell/shell.c index c7d99ff3..f238435f 100644 --- a/src/shell/shell.c +++ b/src/shell/shell.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include #include diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 7b61aa57..2f5aa64d 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + # This file allows OCRE to be included as a Zephyr module. cmake_minimum_required(VERSION 3.20.0) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index e07e78af..c45fbf0c 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + config OCRE bool "Ocre Runtime" default n diff --git a/zephyr/module.yml b/zephyr/module.yml index 31c4472b..a4b5b6cc 100644 --- a/zephyr/module.yml +++ b/zephyr/module.yml @@ -1 +1,6 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + name: ocre diff --git a/zephyr/storage_partition.cmake b/zephyr/storage_partition.cmake index ceb109eb..3a1a2759 100644 --- a/zephyr/storage_partition.cmake +++ b/zephyr/storage_partition.cmake @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + cmake_minimum_required(VERSION 3.20.0) add_custom_command(OUTPUT user_data.bin diff --git a/zephyr/wamr.cmake b/zephyr/wamr.cmake index fa204c93..6aeb36c5 100644 --- a/zephyr/wamr.cmake +++ b/zephyr/wamr.cmake @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + # Determine the ISA of the target and set appropriately if (DEFINED CONFIG_ISA_THUMB2) set(TARGET_ISA THUMB) From e256c0577369ddc522fea4eab8e1f9b97db1e324 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Fri, 19 Dec 2025 16:38:52 +0100 Subject: [PATCH 186/234] ci: remove unused ref parameter Signed-off-by: Marco Casaroli --- .github/workflows/devcontainer-linux.yml | 5 ----- .github/workflows/devcontainer-zephyr.yml | 5 ----- .github/workflows/linux.yml | 3 --- .github/workflows/main.yml | 6 ------ .github/workflows/zephyr.yml | 3 --- 5 files changed, 22 deletions(-) diff --git a/.github/workflows/devcontainer-linux.yml b/.github/workflows/devcontainer-linux.yml index 1cc809c0..57670dba 100644 --- a/.github/workflows/devcontainer-linux.yml +++ b/.github/workflows/devcontainer-linux.yml @@ -7,10 +7,6 @@ name: Linux devcontainer on: workflow_call: - inputs: - ref: - type: string - required: false outputs: devcontainer-tag: value: ${{ jobs.necessary.outputs.devcontainer-tag }} @@ -27,7 +23,6 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 - ref: ${{ inputs.ref }} - uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 id: changed-files diff --git a/.github/workflows/devcontainer-zephyr.yml b/.github/workflows/devcontainer-zephyr.yml index ed5bd4a2..245ed080 100644 --- a/.github/workflows/devcontainer-zephyr.yml +++ b/.github/workflows/devcontainer-zephyr.yml @@ -7,10 +7,6 @@ name: Zephyr devcontainer on: workflow_call: - inputs: - ref: - type: string - required: false outputs: devcontainer-tag: value: ${{ jobs.necessary.outputs.devcontainer-tag }} @@ -27,7 +23,6 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 - ref: ${{ inputs.ref }} - uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 id: changed-files diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index e9941c44..56fa782d 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -13,9 +13,6 @@ on: default: latest required: false type: string - ref: - type: string - required: true jobs: build-linux: diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9d199bf4..050ef184 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -28,8 +28,6 @@ jobs: permissions: contents: read packages: write - with: - ref: ${{ github.sha }} zephyr-devcontainer: name: Zephyr devcontainer @@ -38,8 +36,6 @@ jobs: permissions: contents: read packages: write - with: - ref: ${{ github.sha }} linux: name: Linux @@ -49,7 +45,6 @@ jobs: secrets: inherit with: devcontainer-tag: ${{ needs.linux-devcontainer.outputs.devcontainer-tag }} - ref: ${{ github.sha }} zephyr: name: Zephyr @@ -59,4 +54,3 @@ jobs: secrets: inherit with: devcontainer-tag: ${{ needs.zephyr-devcontainer.outputs.devcontainer-tag }} - ref: ${{ github.sha }} diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index c87a43a1..77852fc4 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -13,9 +13,6 @@ on: default: latest required: false type: string - ref: - type: string - required: true jobs: build-zephyr: From 764b2205691b041dfe981bea0eb2ea6e29aa9489 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Fri, 19 Dec 2025 16:43:47 +0100 Subject: [PATCH 187/234] ci: add C formatting checks Signed-off-by: Marco Casaroli --- .github/workflows/formatting-checks.yml | 30 +++++++++++++++++++++++ .github/workflows/main.yml | 9 +++++++ scripts/check_c_formatting.sh | 32 +++++++++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 .github/workflows/formatting-checks.yml create mode 100755 scripts/check_c_formatting.sh diff --git a/.github/workflows/formatting-checks.yml b/.github/workflows/formatting-checks.yml new file mode 100644 index 00000000..551f4ead --- /dev/null +++ b/.github/workflows/formatting-checks.yml @@ -0,0 +1,30 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + +name: Formatting checks + +on: + workflow_call: + inputs: + devcontainer-tag: + description: The container tag to be used + default: latest + required: false + type: string + +jobs: + format-checks: + name: Formatting checks + runs-on: ubuntu-latest + container: + image: ghcr.io/${{ github.repository }}/devcontainer-linux:${{ inputs.devcontainer-tag }} + steps: + - name: checkout + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Run C Format Checks + run: sh scripts/check_c_formatting.sh diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 050ef184..5cc6eb54 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -37,6 +37,15 @@ jobs: contents: read packages: write + format-checks: + name: Formatting checks + needs: + - linux-devcontainer + uses: ./.github/workflows/formatting-checks.yml + secrets: inherit + with: + devcontainer-tag: ${{ needs.linux-devcontainer.outputs.devcontainer-tag }} + linux: name: Linux needs: diff --git a/scripts/check_c_formatting.sh b/scripts/check_c_formatting.sh new file mode 100755 index 00000000..ad80d707 --- /dev/null +++ b/scripts/check_c_formatting.sh @@ -0,0 +1,32 @@ +#!/bin/bash +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + +# Simple formatting checker for src folder +# Checks all C/C++ files against .clang-format rules +# + +set -e + +ARGUMENT="--dry-run" + +if [ $# -eq 1 ]; then + if [ "$1" == "-f" ]; then + echo "Fixing files in place if necessary" + ARGUMENT="-i" + else + echo "Invalid option: $1" + exit 1 + fi +fi + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +SRC_DIR="$ROOT_DIR/src" + +echo "Checking formatting in $SRC_DIR/.." + +find src -type f '(' -name '*.c' -o -name '*.h' ')' ! -name 'utlist.h' -print0 | \ + xargs -0 -n1 clang-format ${ARGUMENT} -Werror From 50aaacc7b27da406fdbfc8d67315163d35a4ac4e Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Fri, 19 Dec 2025 16:55:14 +0100 Subject: [PATCH 188/234] chore: C formatting Signed-off-by: Marco Casaroli --- src/ocre/container.h | 2 +- src/ocre/context.c | 6 +++--- src/samples/static_checks/posix/download_file.c | 4 ++-- src/shell/container/create.c | 3 ++- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/ocre/container.h b/src/ocre/container.h index d0bde692..eaf8120c 100644 --- a/src/ocre/container.h +++ b/src/ocre/container.h @@ -5,7 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 */ - #include +#include struct ocre_container; diff --git a/src/ocre/context.c b/src/ocre/context.c index a863e7c3..f4869aac 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -376,9 +376,9 @@ int ocre_context_get_num_containers(struct ocre_context *context) const char *ocre_context_get_working_directory(const struct ocre_context *context) { - if (!context) { - return NULL; - } + if (!context) { + return NULL; + } /* We never change this, no need to lock */ diff --git a/src/samples/static_checks/posix/download_file.c b/src/samples/static_checks/posix/download_file.c index 17400bc8..54814f67 100644 --- a/src/samples/static_checks/posix/download_file.c +++ b/src/samples/static_checks/posix/download_file.c @@ -7,7 +7,7 @@ int ocre_download_file(const char *url, const char *filepath) { - /* Not implemented */ + /* Not implemented */ - return -1; + return -1; } diff --git a/src/shell/container/create.c b/src/shell/container/create.c index 704f4022..19298c16 100644 --- a/src/shell/container/create.c +++ b/src/shell/container/create.c @@ -158,7 +158,8 @@ int cmd_container_create_run(struct ocre_context *ctx, const char *argv0, int ar continue; } case 'e': { - const char **new_environment = realloc(environment, sizeof(char *) * (environment_count + 1)); + const char **new_environment = + realloc(environment, sizeof(char *) * (environment_count + 1)); if (!new_environment) { goto cleanup; } From 4fd7869f7c47d1dffbfed07e00e671ad39194c48 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Fri, 19 Dec 2025 16:55:48 +0100 Subject: [PATCH 189/234] chore: license banners Signed-off-by: Marco Casaroli --- scripts/c_array.awk | 6 ++++++ src/shell/container/pause.c | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/scripts/c_array.awk b/scripts/c_array.awk index f9ca0ceb..5b444c71 100644 --- a/scripts/c_array.awk +++ b/scripts/c_array.awk @@ -1,3 +1,9 @@ +#!/bin/bash +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + BEGIN { printf "/* Auto-generated file. DO NOT EDIT! */\n\n" printf "#include \n\n" diff --git a/src/shell/container/pause.c b/src/shell/container/pause.c index 8e84f3e4..ab87c8ac 100644 --- a/src/shell/container/pause.c +++ b/src/shell/container/pause.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include From 2de10b77838e8cdcc93173b61cae1b2828c741e0 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Fri, 19 Dec 2025 16:56:04 +0100 Subject: [PATCH 190/234] fix(ocre): print error message Signed-off-by: Marco Casaroli --- src/ocre/ocre.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ocre/ocre.c b/src/ocre/ocre.c index 4bd6cb6e..5292003d 100644 --- a/src/ocre/ocre.c +++ b/src/ocre/ocre.c @@ -305,6 +305,10 @@ int ocre_destroy_context(struct ocre_context *context) } rc = ocre_destroy_context_locked(context); + if (rc) { + LOG_ERR("Failed to destroy context: rc=%d", rc); + return -1; + } rc = pthread_mutex_unlock(&contexts_mutex); if (rc) { From 28e538bdc57c6fc7e082b716724351bc6b08d9df Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Fri, 19 Dec 2025 17:09:44 +0100 Subject: [PATCH 191/234] chore: fix format Signed-off-by: Marco Casaroli --- src/shell/container.c | 22 +++++++++++----------- src/shell/container/ps.c | 8 +++++++- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/shell/container.c b/src/shell/container.c index cbe52f44..ff51123f 100644 --- a/src/shell/container.c +++ b/src/shell/container.c @@ -41,17 +41,17 @@ static int print_usage(struct ocre_context *ctx, const char *argv0, int argc, ch } static const struct ocre_command commands[] = { - {"help", print_usage}, - {"run", cmd_container_create_run}, - {"create", cmd_container_create_run}, - {"start", cmd_container_start}, - {"stop", cmd_container_stop}, - {"kill", cmd_container_kill}, - {"pause", cmd_container_pause}, - {"unpause", cmd_container_unpause}, - {"wait", cmd_container_wait}, - {"ps", cmd_container_ps}, - {"rm", cmd_container_rm}, + {"help", print_usage}, // + {"run", cmd_container_create_run}, // + {"create", cmd_container_create_run}, // + {"start", cmd_container_start}, // + {"stop", cmd_container_stop}, // + {"kill", cmd_container_kill}, // + {"pause", cmd_container_pause}, // + {"unpause", cmd_container_unpause}, // + {"wait", cmd_container_wait}, // + {"ps", cmd_container_ps}, // + {"rm", cmd_container_rm}, // }; int cmd_container(struct ocre_context *ctx, const char *argv0, int argc, char **argv) diff --git a/src/shell/container/ps.c b/src/shell/container/ps.c index ccf53d32..89b3eedf 100644 --- a/src/shell/container/ps.c +++ b/src/shell/container/ps.c @@ -13,7 +13,13 @@ #include "../command.h" -static const char *container_statuses[] = {"UNKNOWN", "CREATED", "RUNNING", "PAUSED ", "EXITED ", "STOPPED", "ERROR "}; +static const char *container_statuses[] = {"UNKNOWN", // + "CREATED", // + "RUNNING", // + "PAUSED ", // + "EXITED ", // + "STOPPED", // + "ERROR "}; static int usage(const char *argv0) { From c159d894bab052f512a470408ed3a65a871c24b3 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Fri, 19 Dec 2025 17:43:34 +0100 Subject: [PATCH 192/234] build(ocre_api): include GPIO selectively We don't want it for Linux or when OCRE_GPIO is not selected. Signed-off-by: Marco Casaroli --- src/runtime/wamr/ocre_api/CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/runtime/wamr/ocre_api/CMakeLists.txt b/src/runtime/wamr/ocre_api/CMakeLists.txt index 0d794c85..b967413e 100644 --- a/src/runtime/wamr/ocre_api/CMakeLists.txt +++ b/src/runtime/wamr/ocre_api/CMakeLists.txt @@ -17,9 +17,15 @@ target_sources(OcreRuntimeAPI core/core_timer.c core/core_mutex.c core/core_memory.c - ocre_gpio/ocre_gpio.c ) +if (CONFIG_OCRE_GPIO) + target_sources(OcreRuntimeAPI + PRIVATE + ocre_gpio/ocre_gpio.c + ) +endif() + target_link_libraries(OcreRuntimeAPI PUBLIC OcrePlatform From 360f9afa4231ed7344560aa34cb5e28ddab8c169 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Fri, 19 Dec 2025 20:03:48 +0100 Subject: [PATCH 193/234] fix(ocre): rename functions To better names. Signed-off-by: Marco Casaroli --- src/ocre/context.c | 4 ++-- src/ocre/include/ocre/ocre.h | 4 ++-- src/shell/container/ps.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ocre/context.c b/src/ocre/context.c index f4869aac..28cd2978 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -346,7 +346,7 @@ int ocre_context_remove_container(struct ocre_context *context, struct ocre_cont return rc; } -int ocre_context_get_num_containers(struct ocre_context *context) +int ocre_context_get_container_count(struct ocre_context *context) { int rc; int count = 0; @@ -385,7 +385,7 @@ const char *ocre_context_get_working_directory(const struct ocre_context *contex return context->working_directory; } -int ocre_context_list_containers(struct ocre_context *context, struct ocre_container **containers, int max_size) +int ocre_context_get_containers(struct ocre_context *context, struct ocre_container **containers, int max_size) { int rc; int count = 0; diff --git a/src/ocre/include/ocre/ocre.h b/src/ocre/include/ocre/ocre.h index a492c674..cbf0e0eb 100644 --- a/src/ocre/include/ocre/ocre.h +++ b/src/ocre/include/ocre/ocre.h @@ -306,7 +306,7 @@ int ocre_context_remove_container(struct ocre_context *context, struct ocre_cont * * @return The number of containers in the context */ -int ocre_context_get_num_containers(struct ocre_context *context); +int ocre_context_get_container_count(struct ocre_context *context); /** * @brief List containers in the context @@ -320,7 +320,7 @@ int ocre_context_get_num_containers(struct ocre_context *context); * * @return The number of containers listed, negative on failure */ -int ocre_context_list_containers(struct ocre_context *context, struct ocre_container **containers, int max_size); +int ocre_context_get_containers(struct ocre_context *context, struct ocre_container **containers, int max_size); /** * @brief Get the working directory of the context diff --git a/src/shell/container/ps.c b/src/shell/container/ps.c index 89b3eedf..afdd21b8 100644 --- a/src/shell/container/ps.c +++ b/src/shell/container/ps.c @@ -51,7 +51,7 @@ static int list_container(struct ocre_container *container) static int list_containers(struct ocre_context *ctx) { int ret = -1; - int num_containers = ocre_context_get_num_containers(ctx); + int num_containers = ocre_context_get_container_count(ctx); if (num_containers < 0) { fprintf(stderr, "Failed to get number of containers\n"); return -1; @@ -67,7 +67,7 @@ static int list_containers(struct ocre_context *ctx) return -1; } - num_containers = ocre_context_list_containers(ctx, containers, num_containers); + num_containers = ocre_context_get_containers(ctx, containers, num_containers); if (num_containers < 0) { fprintf(stderr, "Failed to list containers\n"); goto finish; From 433c5e987ecdf524596f4956ef22f1c36592c235 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Fri, 19 Dec 2025 21:07:09 +0100 Subject: [PATCH 194/234] chore(samples/demo): formatting Signed-off-by: Marco Casaroli --- src/samples/demo/main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/samples/demo/main.c b/src/samples/demo/main.c index 06e3edbb..db5b055b 100644 --- a/src/samples/demo/main.c +++ b/src/samples/demo/main.c @@ -11,7 +11,11 @@ #include const struct ocre_container_args args = { - .capabilities = (const char *[]){"ocre:api", NULL}, + .capabilities = + (const char *[]){ + "ocre:api", + NULL, + }, }; int main(int argc, char *argv[]) From 868b8110990ac118b286fdb1a8963140379af476 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Fri, 19 Dec 2025 21:07:35 +0100 Subject: [PATCH 195/234] fix(context): return error when not found This function should return error if not found. Signed-off-by: Marco Casaroli --- src/ocre/context.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ocre/context.c b/src/ocre/context.c index 28cd2978..cf23321b 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -74,6 +74,8 @@ static int ocre_context_remove_container_locked(struct ocre_context *context, st return 0; } } + + return -1; } struct ocre_context *ocre_context_create(const char *workdir) From 6db04601118940d5b17f5ff7b6cf513b213deff6 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 22 Dec 2025 08:33:57 +0100 Subject: [PATCH 196/234] chore: c formatting Signed-off-by: Marco Casaroli --- src/ocre/context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ocre/context.c b/src/ocre/context.c index cf23321b..5666f2ca 100644 --- a/src/ocre/context.c +++ b/src/ocre/context.c @@ -74,7 +74,7 @@ static int ocre_context_remove_container_locked(struct ocre_context *context, st return 0; } } - + return -1; } From 561c63f6ed30d534da3c6a2c1ac326db3d4e908f Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 22 Dec 2025 11:41:53 +0100 Subject: [PATCH 197/234] fix(container): restart We now instantiate the runtime when we start the container, not just on create. Allowing the container to be restarted. We also remove the magic numbers from the ocre interface and put them inside WAMR. This is going to be revisited soon. Signed-off-by: Marco Casaroli --- src/ocre/container.c | 9 +-- src/runtime/include/ocre/runtime/vtable.h | 57 +++++++------- src/runtime/wamr/wamr.c | 95 ++++++++++------------- 3 files changed, 70 insertions(+), 91 deletions(-) diff --git a/src/ocre/container.c b/src/ocre/container.c index a4707ad1..3a311ab4 100644 --- a/src/ocre/container.c +++ b/src/ocre/container.c @@ -246,7 +246,7 @@ struct ocre_container *ocre_container_create(const char *img_path, const char *w } container->runtime_context = - container->runtime->create(img_path, workdir, 8192, 8192, capabilities, (const char **)container->argv, + container->runtime->create(img_path, workdir, capabilities, (const char **)container->argv, (const char **)container->envp, mounts); if (!container->runtime_context) { LOG_ERR("Failed to create container"); @@ -359,13 +359,6 @@ int ocre_container_start(struct ocre_container *container) goto error_mutex; } - // rc = pthread_attr_setstacksize(&container->attr, PTHREAD_STACK_MIN); - // rc = pthread_attr_setstacksize(&container->attr, 8192); - // if (rc) { - // LOG_ERR("Failed to set stack size: rc=%d", rc); - // goto error_attr; - // } - struct container_thread_params *params; params = malloc(sizeof(struct container_thread_params)); if (!params) { diff --git a/src/runtime/include/ocre/runtime/vtable.h b/src/runtime/include/ocre/runtime/vtable.h index 4d0f15d9..94dd5c9d 100644 --- a/src/runtime/include/ocre/runtime/vtable.h +++ b/src/runtime/include/ocre/runtime/vtable.h @@ -17,7 +17,8 @@ * * This is the interface between the ocre container and the runtime engine. * - * These functions are guaranteed to be operated according to the Ocre Container lifecycle specification. + * These functions are guaranteed to be operated according to the Ocre Container lifecycle + * specification. * * Please refer to the full documentation for more details. * @@ -29,16 +30,16 @@ struct ocre_runtime_vtable { * * This is the name of the runtime engine. Should be a zero-terminated string. * - * It should be unique among all registered runtime engines. Please refer to the full documentation for the list - * of assigned runtime engine names. + * It should be unique among all registered runtime engines. Please refer to the full + * documentation for the list of assigned runtime engine names. */ const char *const runtime_name; /** * @brief Initialize the runtime engine * - * This function is called when the runtime engine is initialized. It is called only one on start and before any - * other functions are called. + * This function is called when the runtime engine is initialized. It is called only once on + * start and before any other functions are called. * * @return 0 on success, non-zero on failure */ @@ -58,29 +59,29 @@ struct ocre_runtime_vtable { * * This function is called when a new runtime instance is created. * - * This function will return an opaque pointer to the context of the runtime instance. It can be anything - * managed internally by the runtime. It cannot be NULL, as it will indicate error. This value is passed as a - * parameter to the other functions in this interface. + * This function will return an opaque pointer to the context of the runtime instance. It + * can be anything managed internally by the runtime. It cannot be NULL, as it will indicate + * error. This value is passed as a parameter to the other functions in this interface. * * @param img_path Absolute path to the image file * @param workdir Working directory for the runtime instance. Can be NULL. - * @param stack_size Stack size for the runtime instance - * @param heap_size Heap size for the runtime instance * @param capabilities A NULL-terminated array of capabilities for the runtime instance - * @param argv A NULL-terminated array of command line arguments to be passed to the container - * @param envp A NULL-terminated array of environment variables to be passed to the container + * @param argv A NULL-terminated array of command line arguments to be passed to the + * container + * @param envp A NULL-terminated array of environment variables to be passed to the + * container * @param mounts Mount points for the runtime instance * * @return Pointer to the runtime context on success, NULL on failure */ - void *(*create)(const char *img_path, const char *workdir, size_t stack_size, size_t heap_size, - const char **capabilities, const char **argv, const char **envp, const char **mounts); + void *(*create)(const char *img_path, const char *workdir, const char **capabilities, + const char **argv, const char **envp, const char **mounts); /** * @brief Destroy a runtime instance * - * This function is called when a runtime instance is destroyed. This is guaranteed to be called only when the - * container should not be running or paused. + * This function is called when a runtime instance is destroyed. This is guaranteed to be + * called only when the container should not be running or paused. * * @param runtime_context Pointer to the runtime context * @return 0 on success, non-zero on failure @@ -90,11 +91,12 @@ struct ocre_runtime_vtable { /** * @brief Thread execute function for the runtime. * - * This function is called inside a thread when the container is started. It should execute the container's main - * function, block and eventually return the exit code. + * This function is called inside a thread when the container is started. It should execute + * the container's main function, block and eventually return the exit code. * * @param runtime_context Pointer to the runtime context returned by create - * @param cond Pointer to the conditional variable to signal when the instance is ready to be killed + * @param cond Pointer to the conditional variable to signal when the instance is ready to + * be killed * * @return status code of the execution: 0 on success, non-zero on failure */ @@ -104,8 +106,8 @@ struct ocre_runtime_vtable { /** * @brief Stop a runtime instance * - * This function is called when a runtime instance is requested to stop. This is guaranteed to be called only - * when the container is running or paused. + * This function is called when a runtime instance is requested to stop. This is guaranteed + * to be called only when the container is running or paused. * * @param runtime_context Pointer to the runtime context * @return 0 on success, non-zero on failure @@ -115,8 +117,9 @@ struct ocre_runtime_vtable { /** * @brief Kill a runtime instance * - * This function is called when a runtime instance is requested to be killed. This is guaranteed to be called - * only when the container is running. This should terminate the container immediately. + * This function is called when a runtime instance is requested to be killed. This is + * guaranteed to be called only when the container is running. This should terminate the + * container immediately. * * @param runtime_context Pointer to the runtime context * @return 0 on success, non-zero on failure @@ -126,8 +129,8 @@ struct ocre_runtime_vtable { /** * @brief Pause a runtime instance * - * This function is called when a runtime instance is requested to be paused. This is guaranteed to be called - * only when the container is running. + * This function is called when a runtime instance is requested to be paused. This is + * guaranteed to be called only when the container is running. * * @param runtime_context Pointer to the runtime context * @return 0 on success, non-zero on failure @@ -137,8 +140,8 @@ struct ocre_runtime_vtable { /** * @brief Unpause a runtime instance * - * This function is called when a runtime instance is requested to be unpaused. This is guaranteed to be called - * only when the container is paused. + * This function is called when a runtime instance is requested to be unpaused. This is + * guaranteed to be called only when the container is paused. * * @param runtime_context Pointer to the runtime context * @return 0 on success, non-zero on failure diff --git a/src/runtime/wamr/wamr.c b/src/runtime/wamr/wamr.c index 7d7525ec..a05db2d5 100644 --- a/src/runtime/wamr/wamr.c +++ b/src/runtime/wamr/wamr.c @@ -43,36 +43,55 @@ struct wamr_context { char **argv; char **envp; bool uses_ocre_api; + bool uses_shared_heap; }; static int instance_execute(void *runtime_context, pthread_cond_t *cond) { struct wamr_context *context = runtime_context; - wasm_module_inst_t module_inst = context->module_inst; + + context->module_inst = + wasm_runtime_instantiate(context->module, 8192, 8192, context->error_buf, sizeof(context->error_buf)); + if (!context->module_inst) { + LOG_ERR("Failed to instantiate module: %s, for context %p", context->error_buf, context); + return -1; + } + + if (context->uses_ocre_api) { + ocre_module_context_t *mod = ocre_register_module(context->module_inst); + wasm_runtime_set_custom_data(context->module_inst, mod); + } + + if (context->uses_shared_heap) { + if (!wasm_runtime_attach_shared_heap(context->module_inst, _shared_heap)) { + LOG_ERR("Failed to attach shared heap"); + } + LOG_INF("Shared heap capability enabled"); + } /* Clear any previous exceptions */ - wasm_runtime_clear_exception(module_inst); + wasm_runtime_clear_exception(context->module_inst); /* Notify the starting waiter that we are ready * We should notify only after we are ready to process the kill call. - * In WAMR, this is managed by the exception message, so we are good if we just cleared the exception. + * In WAMR, this is managed by the exception message, so we are good if we just cleared the + * exception. */ int rc = pthread_cond_signal(cond); if (rc) { LOG_WRN("Failed to signal start conditional variable: rc=%d", rc); - return -1; } /* Execute main function */ const char *exception = NULL; - if (!wasm_application_execute_main(module_inst, 1, context->argv)) { + if (!wasm_application_execute_main(context->module_inst, 1, context->argv)) { LOG_WRN("Main function returned error in context %p exception: %s", context, exception ? exception : "None"); - exception = wasm_runtime_get_exception(module_inst); + exception = wasm_runtime_get_exception(context->module_inst); if (exception) { LOG_ERR("Container %p exception: %s", context, exception); } @@ -83,13 +102,19 @@ static int instance_execute(void *runtime_context, pthread_cond_t *cond) LOG_INF("Cleaning up module resources"); - ocre_cleanup_module_resources(module_inst); + ocre_cleanup_module_resources(context->module_inst); + + ocre_unregister_module(context->module_inst); } LOG_INF("Context %p completed successfully", context); int exit_code = wasm_runtime_get_wasi_exit_code(context->module_inst); + wasm_runtime_deinstantiate(context->module_inst); + + context->module_inst = NULL; + return exit_code; } @@ -189,8 +214,8 @@ static int runtime_deinit(void) return 0; } -static void *instance_create(const char *img_path, const char *workdir, size_t stack_size, size_t heap_size, - const char **capabilities, const char **argv, const char **envp, const char **mounts) +static void *instance_create(const char *img_path, const char *workdir, const char **capabilities, const char **argv, + const char **envp, const char **mounts) { struct wamr_context *context = NULL; char **dir_map_list = NULL; @@ -279,7 +304,10 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s /* Process capabilities */ for (const char **cap = capabilities; cap && *cap; cap++) { - if (0) { + if (!strcmp(*cap, "ocre:shared_heap")) { + context->uses_shared_heap = true; + } else if (!strcmp(*cap, "ocre:api")) { + context->uses_ocre_api = true; } #if CONFIG_OCRE_NETWORKING else if (!strcmp(*cap, "networking")) { @@ -366,47 +394,13 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s dir_map_list_len++; /* Add the NULL */ + dir_map_list[dir_map_list_len] = NULL; } wasm_runtime_set_wasi_args(context->module, NULL, 0, (const char **)dir_map_list, dir_map_list_len, envp, envn, context->argv, argc + 1); - context->module_inst = wasm_runtime_instantiate(context->module, stack_size, heap_size, context->error_buf, - sizeof(context->error_buf)); - if (!context->module_inst) { - LOG_ERR("Failed to instantiate module: %s, for context %p", context->error_buf, context); - goto error_module; - } - - for (const char **cap = capabilities; cap && *cap; cap++) { - if (0) { - } -#if CONFIG_OCRE_NETWORKING - else if (!strcmp(*cap, "networking")) { - /* already set up */ - } -#endif -#if CONFIG_OCRE_FILESYSTEM - else if (!strcmp(*cap, "filesystem")) { - /* already set up */ - } -#endif - else if (!strcmp(*cap, "ocre:api")) { - context->uses_ocre_api = true; - ocre_module_context_t *mod = ocre_register_module(context->module_inst); - wasm_runtime_set_custom_data(context->module_inst, mod); - } else if (!strcmp(*cap, "ocre:shared_heap")) { - if (!wasm_runtime_attach_shared_heap(context->module_inst, _shared_heap)) { - LOG_ERR("Failed to attach shared heap"); - goto error_instance; - } - LOG_INF("Shared heap capability enabled"); - } else { - LOG_WRN("Capability '%s' not supported by runtime", *cap); - } - } - for (char **dir_map = dir_map_list; dir_map && *dir_map; dir_map++) { free(*dir_map); } @@ -415,9 +409,6 @@ static void *instance_create(const char *img_path, const char *workdir, size_t s return context; -error_instance: - wasm_runtime_deinstantiate(context->module_inst); - error_module: wasm_runtime_unload(context->module); @@ -473,14 +464,6 @@ static int instance_destroy(void *runtime_context) return -1; } - if (context->uses_ocre_api) { - ocre_unregister_module(context->module_inst); - } - - wasm_runtime_deinstantiate(context->module_inst); - - context->module_inst = NULL; - wasm_runtime_unload(context->module); if (ocre_unload_file(context->buffer, context->size)) { From abf75882bfcb1280b6260b380b948735b5d3fe12 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 22 Dec 2025 11:42:57 +0100 Subject: [PATCH 198/234] feat(public_api): separate include files Make the files smaller and easier to test by separating them and including all of them from the top level ocre.h Signed-off-by: Marco Casaroli --- src/ocre/include/ocre/container.h | 168 +++++++++ src/ocre/include/ocre/context.h | 197 ++++++++++ src/ocre/include/ocre/library.h | 103 ++++++ src/ocre/include/ocre/ocre.h | 424 +--------------------- src/runtime/include/ocre/runtime/vtable.h | 4 +- 5 files changed, 473 insertions(+), 423 deletions(-) create mode 100644 src/ocre/include/ocre/container.h create mode 100644 src/ocre/include/ocre/context.h create mode 100644 src/ocre/include/ocre/library.h diff --git a/src/ocre/include/ocre/container.h b/src/ocre/include/ocre/container.h new file mode 100644 index 00000000..72540293 --- /dev/null +++ b/src/ocre/include/ocre/container.h @@ -0,0 +1,168 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef OCRE_CONTAINER_H +#define OCRE_CONTAINER_H + +/** + * @brief The possible status of a container + * + * This enum represents the possible status of a container. The container status are all side-effects from the + * container's lifecycle. + * + * The status OCRE_CONTAINER_STATUS_EXITED is a transient status that indicates the container has exited but we did not + * get the exit code yet. Upon calling ocre_container_wait(), the status will be updated to + * OCRE_CONTAINER_STATUS_STOPPED in case it was OCRE_CONTAINER_STATUS_EXITED. + */ +typedef enum { + OCRE_CONTAINER_STATUS_UNKNOWN = 0, /**< Status is unknown */ + OCRE_CONTAINER_STATUS_CREATED, /**< Container has been created. */ + OCRE_CONTAINER_STATUS_RUNNING, /**< Container is currently running. */ + OCRE_CONTAINER_STATUS_PAUSED, /**< Container is currently paused. */ + OCRE_CONTAINER_STATUS_EXITED, /**< Container has exited but we did not get the exit code yet. */ + OCRE_CONTAINER_STATUS_STOPPED, /**< Container has been stopped. */ + OCRE_CONTAINER_STATUS_ERROR, /**< An error occurred with the container. */ +} ocre_container_status_t; + +/** + * @class ocre_container + * @headerfile ocre.h + * @brief Ocre Container + * + * An opaque structure representing the container. It should be used to interact with Ocre Library and passed around as + * pointers. + * + * An Ocre Container is an application running on a runtime engine. + */ +struct ocre_container; + +/** + * @brief Start a container + * @memberof ocre_container + * + * Starts a container in the context. The container must be in the CREATED or STOPPED states. Calling this function on a + * container on other states will result in error. + * + * @param container A pointer to the container to start + * + * @return Zero on success, non-zero on failure + */ +int ocre_container_start(struct ocre_container *container); + +/** + * @brief Get the status of a container + * @memberof ocre_container + * + * Returns the status of a container in the context. + * + * @param container A pointer to the container to get the status of + * + * @return The status of the container. UNKNOWN on failure + */ +ocre_container_status_t ocre_container_get_status(struct ocre_container *container); + +/** + * @brief Get the ID of a container + * @memberof ocre_container + * + * Returns a pointer to a C string containing the ID of the container. This string is owned by the container and is + * valid until the container is destroyed. Should not be modified or freed by the caller. + * + * @param container A pointer to the container to get the ID of + * + * @return A pointer to the ID string, or NULL on failure + */ +const char *ocre_container_get_id(const struct ocre_container *container); + +/** + * @brief Get the image of a container + * @memberof ocre_container + * + * Returns a pointer to a C string containing the image of the container. This string is owned by the container and is + * valid until the container is destroyed. Should not be modified or freed by the caller. + * + * @param container A pointer to the container to get the image of + * + * @return A pointer to the image string, or NULL on failure + */ +const char *ocre_container_get_image(const struct ocre_container *container); + +/** + * @brief Pause a container + * @memberof ocre_container + * + * Pauses a container in the context. The container must be in the RUNNING state, otherwise it will fail. + * + * Note: This is currently not supported in WAMR containers. + * + * @param container A pointer to the container to pause + * + * @return Zero on success, non-zero on failure + */ +int ocre_container_pause(struct ocre_container *container); + +/** + * @brief Unpause a container + * @memberof ocre_container + * + * Unpauses a container in the context. The container must be in the PAUSED state, otherwise it will fail. + * + * Note: This is currently not supported in WAMR containers. + * + * @param container A pointer to the container to unpause + * + * @return Zero on success, non-zero on failure + */ +int ocre_container_unpause(struct ocre_container *container); + +/** + * @brief Gracefully stop a container + * @memberof ocre_container + * + * Stops a container in the context. The container must be in the RUNNING state, otherwise it will fail. + * + * The operation will signal the container to stop, and after a grace period, it will be forcefully terminated if not + * exited. + * + * Note: This is currently not supported in WAMR containers. + * + * @param container A pointer to the container to stop + * + * @return Zero on success, non-zero on failure + */ +int ocre_container_stop(struct ocre_container *container); + +/** + * @brief Forcefully terminate a container + * @memberof ocre_container + * + * Terminates a container in the context. The container must be in the RUNNING state, otherwise it will fail. + * + * @param container A pointer to the container to terminate + * + * @return Zero on success, non-zero on failure + */ +int ocre_container_kill(struct ocre_container *container); + +/** + * @brief Wait for a container to exit + * @memberof ocre_container + * + * If the container is STOPPED, returns the exit status of the container. + * + * If the container is RUNNING or PAUSED, waits for the container to exit. + * + * If the container is in other states, it will fail. + * + * @param container A pointer to the container to wait for + * @param[out] status A pointer to store the exit status of the container. Can be NULL + * + * @return Zero on success, non-zero on failure + */ +int ocre_container_wait(struct ocre_container *container, int *status); + +#endif /* OCRE_CONTAINER_H */ diff --git a/src/ocre/include/ocre/context.h b/src/ocre/include/ocre/context.h new file mode 100644 index 00000000..a90ad0c1 --- /dev/null +++ b/src/ocre/include/ocre/context.h @@ -0,0 +1,197 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef OCRE_CONTEXT_H +#define OCRE_CONTEXT_H + +#include + +struct ocre_container; + +/** + * @class ocre_context + * @headerfile ocre.h + * @brief Ocre Context + * + * The context is created by ocre_create_context() and destroyed by ocre_destroy_context(). It is used to interact with + * Ocre Library and passed around as pointers. + * + * The Ocre Context is a manager for a set of containers on their own runtime engines. + */ +struct ocre_context; + +/** + * @brief Container arguments + * @headerfile ocre.h + * + * A structure representing container arguments. These are passed to the runtime engine to define + * the container's behavior. + * + * The parameters are pointers to a NULL-terminated arrays of pointers standard (zero-terminated) character C strings. + */ +struct ocre_container_args { + /** @brief arguments to the container + * + * It is passed as parameters to the container's entry point. This is a NULL-terminated array of pointers to + * standard (zero-terminated) character C strings. + * + * Should not include the container's name. Any value here, starting from argv[0] will be passed to the + * container's entry point as argv[1] and so on. + * + * Example: + * @code + * const char *argv[] = { + * "arg1", + * "arg2", + * NULL + * }; + * @endcode + */ + const char **argv; + + /** @brief environment variables to the container + * + * It is passed as environment variables to the container's entry point. + * + * The values should be in the format "VAR=value". + * + * Example: + * @code + * const char *envp[] = { + * "VAR1=value1", + * "VAR2=value2", + * NULL + * }; + * @endcode + */ + const char **envp; + + /** @brief enabled permissions and features for the container + * + * It is used to enable specific container features and permissions. The possible values depends on the + * implementation. Check the full documentation for more details. + * + * This is a NULL-terminated array of pointers to standard (zero-terminated) character C strings. + * + * Example: + * @code + * const char *capabilities[] = { + * "filesystem", + * "networking", + * "ocre:api", + * NULL + * }; + * @endcode + */ + const char **capabilities; + + /** @brief Virtual mounts for the container. + * + * It is used to expose files. The format is in the form of "source:destination". + * + * This is a NULL-terminated array of pointers to standard (zero-terminated) character C strings and is in the + * form ":" + * + * The current implementation supports the following: + * - "/absolute/path/to/dir/on/host:/absolute/path/in/container" to mount a directory from the host into the + * container. + * + * Note: relative path, volumes and file-mounts are not yet supported. + * + * The Ocre Process should have the necessary permissions to access the source directory. + * + * Example: + * @code + * const char *mounts[] = { + * "/dev:/dev", + * NULL + * }; + * @endcode + */ + const char **mounts; +}; + +/** + * @brief Creates a new container within the given context + * @memberof ocre_context + * + * Creates a new container within the given context. The container will be created using the specified image, runtime, + * container ID, and arguments. If the container is detached, it will be run in the background. + * + * @param context A pointer to the context in which to create the container + * @param image The name of the image to use for the container + * @param runtime The name of the runtime engine to use for the container + * @param container_id The ID to assign to the container. Can be NULL, in which case a random ID will be generated + * @param detached Whether the container should be detached (run in the background) or not + * @param arguments The container arguments to pass to the container. Can be NULL + * + * @return A pointer to the newly created container, or NULL on failure + */ +struct ocre_container *ocre_context_create_container(struct ocre_context *context, const char *image, + const char *const runtime, const char *container_id, bool detached, + const struct ocre_container_args *arguments); + +/** + * @brief Get a container by its ID + * @memberof ocre_context + * + * @param context A pointer to the context in which to get the container. + * @param id The ID of the container to get. + * + * @return A pointer to the container, or NULL if not found + */ +struct ocre_container *ocre_context_get_container_by_id(struct ocre_context *context, const char *id); + +/** + * @brief Remove a container + * @memberof ocre_context + * + * @param context A pointer to the context in which to remove the container. + * @param container A pointer to the container to remove. + * + * @return 0 on success, non-zero on failure + */ +int ocre_context_remove_container(struct ocre_context *context, struct ocre_container *container); + +/** + * @brief Get the number of containers in the context + * @memberof ocre_context + * + * @param context A pointer to the context in which to get the number of containers + * + * @return The number of containers in the context + */ +int ocre_context_get_container_count(struct ocre_context *context); + +/** + * @brief List containers in the context + * @memberof ocre_context + * + * This function will populate the provided array with pointers to the containers, up to the maximum size. + * + * @param context A pointer to the context in which to list containers + * @param[out] containers A pointer to an array of pointers to containers + * @param[in] max_size The maximum size of the array + * + * @return The number of containers listed, negative on failure + */ +int ocre_context_get_containers(struct ocre_context *context, struct ocre_container **containers, int max_size); + +/** + * @brief Get the working directory of the context + * @memberof ocre_context + * + * Returns a pointer to a C string containing the working directory. This string is owned by the context and is valid + * until the context is destroyed. Should not be modified or freed by the caller. + * + * @param context A pointer to the context in which to get the working directory + * + * @return A pointer to the working directory string, or NULL on failure + */ +const char *ocre_context_get_working_directory(const struct ocre_context *context); + +#endif /* OCRE_CONTEXT_H */ diff --git a/src/ocre/include/ocre/library.h b/src/ocre/include/ocre/library.h new file mode 100644 index 00000000..eaa56210 --- /dev/null +++ b/src/ocre/include/ocre/library.h @@ -0,0 +1,103 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef OCRE_LIBRARY_H +#define OCRE_LIBRARY_H + +#include + +/** + * @brief Build configuration of the Ocre Library + * @headerfile ocre.h + * + * There should only be only one instance of this structure in the program. And it must be in constant read-only memory. + * It is set at build-time and should only be read-only to the user. + */ +struct ocre_config { + const char *version; /**< Version of the Ocre Library */ + const char *commit_id; /**< Commit ID of the build tree */ + const char *build_info; /**< Host build information */ + const char *build_date; /**< Build date */ +}; + +/** + * @brief The instance of configuration of the Ocre Library is constant and compiled-in. + */ +extern const struct ocre_config ocre_build_configuration; + +/** + * @class ocre_context + * @headerfile ocre.h + * @brief Ocre Context + * + * The context is created by ocre_create_context() and destroyed by ocre_destroy_context(). It is used to interact with + * Ocre Library and passed around as pointers. + * + * The Ocre Context is a manager for a set of containers on their own runtime engines. + */ +struct ocre_context; + +/** + * @brief Initialize the Ocre Library and register runtime engines + * + * This function initializes the Ocre Library and register optional additional runtime engines. It must be called + * exactly once before any other Ocre Library functions are used. + * + * @param vtable A pointer to a NULL-terminated Array of runtime engine vtables to register. Can be NULL. + * + * @return 0 on success, non-zero on failure + */ +int ocre_initialize(const struct ocre_runtime_vtable *const vtable[]); + +/** + * @brief Creates a new Ocre Context + * + * Creates a new Ocre Context with the specified working directory. + * + * Creating multiple Ocre Contexts is allowed, but each context must have its own working directory. Using the same + * working directory for multiple contexts will result in an error. + * + * @param workdir The working directory for the new context. Absolute path, NULL for default. + * + * @return a pointer to the newly created Ocre Context on success, NULL on failure + */ +struct ocre_context *ocre_create_context(const char *workdir); + +/** + * @brief Destroys an Ocre Context + * + * Destroys an Ocre Context. If there are any running containers, they will be killed and removed. + * + * @param context A pointer to the Ocre Context to destroy. + * + * @return 0 on success, non-zero on failure + */ +int ocre_destroy_context(struct ocre_context *context); + +/** + * @brief Deinitializes the Ocre Library + * + * Deinitializes the Ocre Library, destroying all contexts and containers. + * + * Any errors will be ignored. + */ +void ocre_deinitialize(void); + +/** + * @brief Check if a container or image ID is valid + * @memberof ocre_context + * + * Checks if a container or image ID is valid. A valid container or image ID must not be NULL, empty, or start with a + * dot '.'. It can only contain alphanumeric characters, dots, underscores, and hyphens. + * + * @param id A pointer to the container or image ID to check + * + * @return Zero if invalid, 1 if valid + */ +int ocre_is_valid_id(const char *id); + +#endif /* OCRE_LIBRARY_H */ diff --git a/src/ocre/include/ocre/ocre.h b/src/ocre/include/ocre/ocre.h index cbf0e0eb..2e13a6b7 100644 --- a/src/ocre/include/ocre/ocre.h +++ b/src/ocre/include/ocre/ocre.h @@ -16,11 +16,6 @@ #ifndef OCRE_H #define OCRE_H -#include -#include - -#include - /** * @mainpage Ocre Runtime Library Index * # Ocre Runtime Library @@ -56,421 +51,8 @@ * See ocre_runtime_vtable class for documentation. */ -/** - * @brief The possible status of a container - * - * This enum represents the possible status of a container. The container status are all side-effects from the - * container's lifecycle. - * - * The status OCRE_CONTAINER_STATUS_EXITED is a transient status that indicates the container has exited but we did not - * get the exit code yet. Upon calling ocre_container_wait(), the status will be updated to - * OCRE_CONTAINER_STATUS_STOPPED in case it was OCRE_CONTAINER_STATUS_EXITED. - */ -typedef enum { - OCRE_CONTAINER_STATUS_UNKNOWN = 0, /**< Status is unknown */ - OCRE_CONTAINER_STATUS_CREATED, /**< Container has been created. */ - OCRE_CONTAINER_STATUS_RUNNING, /**< Container is currently running. */ - OCRE_CONTAINER_STATUS_PAUSED, /**< Container is currently paused. */ - OCRE_CONTAINER_STATUS_EXITED, /**< Container has exited but we did not get the exit code yet. */ - OCRE_CONTAINER_STATUS_STOPPED, /**< Container has been stopped. */ - OCRE_CONTAINER_STATUS_ERROR, /**< An error occurred with the container. */ -} ocre_container_status_t; - -/** - * @brief Build configuration of the Ocre Library - * @headerfile ocre.h - * - * There should only be only one instance of this structure in the program. And it must be in constant read-only memory. - * It is set at build-time and should only be read-only to the user. - */ -struct ocre_config { - const char *version; /**< Version of the Ocre Library */ - const char *commit_id; /**< Commit ID of the build tree */ - const char *build_info; /**< Host build information */ - const char *build_date; /**< Build date */ -}; - -/** - * @brief The instance of configuration of the Ocre Library is constant and compiled-in. - */ -extern const struct ocre_config ocre_build_configuration; - -/** - * @class ocre_context - * @headerfile ocre.h - * @brief Ocre Context - * - * The context is created by ocre_create_context() and destroyed by ocre_destroy_context(). It is used to interact with - * Ocre Library and passed around as pointers. - * - * The Ocre Context is a manager for a set of containers on their own runtime engines. - */ -struct ocre_context; - -/** - * @brief Container arguments - * @headerfile ocre.h - * - * A structure representing container arguments. These are passed to the runtime engine to define - * the container's behavior. - * - * The parameters are pointers to a NULL-terminated arrays of pointers standard (zero-terminated) character C strings. - */ -struct ocre_container_args { - /** @brief arguments to the container - * - * It is passed as parameters to the container's entry point. This is a NULL-terminated array of pointers to - * standard (zero-terminated) character C strings. - * - * Should not include the container's name. Any value here, starting from argv[0] will be passed to the - * container's entry point as argv[1] and so on. - * - * Example: - * @code - * const char *argv[] = { - * "arg1", - * "arg2", - * NULL - * }; - * @endcode - */ - const char **argv; - - /** @brief environment variables to the container - * - * It is passed as environment variables to the container's entry point. - * - * The values should be in the format "VAR=value". - * - * Example: - * @code - * const char *envp[] = { - * "VAR1=value1", - * "VAR2=value2", - * NULL - * }; - * @endcode - */ - const char **envp; - - /** @brief enabled permissions and features for the container - * - * It is used to enable specific container features and permissions. The possible values depends on the - * implementation. Check the full documentation for more details. - * - * This is a NULL-terminated array of pointers to standard (zero-terminated) character C strings. - * - * Example: - * @code - * const char *capabilities[] = { - * "filesystem", - * "networking", - * "ocre:api", - * NULL - * }; - * @endcode - */ - const char **capabilities; - - /** @brief Virtual mounts for the container. - * - * It is used to expose files. The format is in the form of "source:destination". - * - * This is a NULL-terminated array of pointers to standard (zero-terminated) character C strings and is in the - * form ":" - * - * The current implementation supports the following: - * - "/absolute/path/to/dir/on/host:/absolute/path/in/container" to mount a directory from the host into the - * container. - * - * Note: relative path, volumes and file-mounts are not yet supported. - * - * The Ocre Process should have the necessary permissions to access the source directory. - * - * Example: - * @code - * const char *mounts[] = { - * "/dev:/dev", - * NULL - * }; - * @endcode - */ - const char **mounts; -}; - -/** - * @class ocre_container - * @headerfile ocre.h - * @brief Ocre Container - * - * An opaque structure representing the container. It should be used to interact with Ocre Library and passed around as - * pointers. - * - * An Ocre Container is an application running on a runtime engine. - */ -struct ocre_container; - -/** - * @brief Initialize the Ocre Library and register runtime engines - * - * This function initializes the Ocre Library and register optional additional runtime engines. It must be called - * exactly once before any other Ocre Library functions are used. - * - * @param vtable A pointer to a NULL-terminated Array of runtime engine vtables to register. Can be NULL. - * - * @return 0 on success, non-zero on failure - */ -int ocre_initialize(const struct ocre_runtime_vtable *const vtable[]); - -/** - * @brief Creates a new Ocre Context - * - * Creates a new Ocre Context with the specified working directory. - * - * Creating multiple Ocre Contexts is allowed, but each context must have its own working directory. Using the same - * working directory for multiple contexts will result in an error. - * - * @param workdir The working directory for the new context. Absolute path, NULL for default. - * - * @return a pointer to the newly created Ocre Context on success, NULL on failure - */ -struct ocre_context *ocre_create_context(const char *workdir); - -/** - * @brief Destroys an Ocre Context - * - * Destroys an Ocre Context. If there are any running containers, they will be killed and removed. - * - * @param context A pointer to the Ocre Context to destroy. - * - * @return 0 on success, non-zero on failure - */ -int ocre_destroy_context(struct ocre_context *context); - -/** - * @brief Deinitializes the Ocre Library - * - * Deinitializes the Ocre Library, destroying all contexts and containers. - * - * Any errors will be ignored. - */ -void ocre_deinitialize(void); - -/** - * @brief Creates a new container within the given context - * @memberof ocre_context - * - * Creates a new container within the given context. The container will be created using the specified image, runtime, - * container ID, and arguments. If the container is detached, it will be run in the background. - * - * @param context A pointer to the context in which to create the container - * @param image The name of the image to use for the container - * @param runtime The name of the runtime engine to use for the container - * @param container_id The ID to assign to the container. Can be NULL, in which case a random ID will be generated - * @param detached Whether the container should be detached (run in the background) or not - * @param arguments The container arguments to pass to the container. Can be NULL - * - * @return A pointer to the newly created container, or NULL on failure - */ -struct ocre_container *ocre_context_create_container(struct ocre_context *context, const char *image, - const char *const runtime, const char *container_id, bool detached, - const struct ocre_container_args *arguments); - -/** - * @brief Get a container by its ID - * @memberof ocre_context - * - * @param context A pointer to the context in which to get the container. - * @param id The ID of the container to get. - * - * @return A pointer to the container, or NULL if not found - */ -struct ocre_container *ocre_context_get_container_by_id(struct ocre_context *context, const char *id); - -/** - * @brief Remove a container - * @memberof ocre_context - * - * @param context A pointer to the context in which to remove the container. - * @param container A pointer to the container to remove. - * - * @return 0 on success, non-zero on failure - */ -int ocre_context_remove_container(struct ocre_context *context, struct ocre_container *container); - -/** - * @brief Get the number of containers in the context - * @memberof ocre_context - * - * @param context A pointer to the context in which to get the number of containers - * - * @return The number of containers in the context - */ -int ocre_context_get_container_count(struct ocre_context *context); - -/** - * @brief List containers in the context - * @memberof ocre_context - * - * This function will populate the provided array with pointers to the containers, up to the maximum size. - * - * @param context A pointer to the context in which to list containers - * @param[out] containers A pointer to an array of pointers to containers - * @param[in] max_size The maximum size of the array - * - * @return The number of containers listed, negative on failure - */ -int ocre_context_get_containers(struct ocre_context *context, struct ocre_container **containers, int max_size); - -/** - * @brief Get the working directory of the context - * @memberof ocre_context - * - * Returns a pointer to a C string containing the working directory. This string is owned by the context and is valid - * until the context is destroyed. Should not be modified or freed by the caller. - * - * @param context A pointer to the context in which to get the working directory - * - * @return A pointer to the working directory string, or NULL on failure - */ -const char *ocre_context_get_working_directory(const struct ocre_context *context); - -/** - * @brief Check if a container or image ID is valid - * @memberof ocre_context - * - * Checks if a container or image ID is valid. A valid container or image ID must not be NULL, empty, or start with a - * dot '.'. It can only contain alphanumeric characters, dots, underscores, and hyphens. - * - * @param id A pointer to the container or image ID to check - * - * @return Zero if invalid, 1 if valid - */ -int ocre_is_valid_id(const char *id); - -/** - * @brief Start a container - * @memberof ocre_container - * - * Starts a container in the context. The container must be in the CREATED or STOPPED states. Calling this function on a - * container on other states will result in error. - * - * @param container A pointer to the container to start - * - * @return Zero on success, non-zero on failure - */ -int ocre_container_start(struct ocre_container *container); - -/** - * @brief Get the status of a container - * @memberof ocre_container - * - * Returns the status of a container in the context. - * - * @param container A pointer to the container to get the status of - * - * @return The status of the container. UNKNOWN on failure - */ -ocre_container_status_t ocre_container_get_status(struct ocre_container *container); - -/** - * @brief Get the ID of a container - * @memberof ocre_container - * - * Returns a pointer to a C string containing the ID of the container. This string is owned by the container and is - * valid until the container is destroyed. Should not be modified or freed by the caller. - * - * @param container A pointer to the container to get the ID of - * - * @return A pointer to the ID string, or NULL on failure - */ -const char *ocre_container_get_id(const struct ocre_container *container); - -/** - * @brief Get the image of a container - * @memberof ocre_container - * - * Returns a pointer to a C string containing the image of the container. This string is owned by the container and is - * valid until the container is destroyed. Should not be modified or freed by the caller. - * - * @param container A pointer to the container to get the image of - * - * @return A pointer to the image string, or NULL on failure - */ -const char *ocre_container_get_image(const struct ocre_container *container); - -/** - * @brief Pause a container - * @memberof ocre_container - * - * Pauses a container in the context. The container must be in the RUNNING state, otherwise it will fail. - * - * Note: This is currently not supported in WAMR containers. - * - * @param container A pointer to the container to pause - * - * @return Zero on success, non-zero on failure - */ -int ocre_container_pause(struct ocre_container *container); - -/** - * @brief Unpause a container - * @memberof ocre_container - * - * Unpauses a container in the context. The container must be in the PAUSED state, otherwise it will fail. - * - * Note: This is currently not supported in WAMR containers. - * - * @param container A pointer to the container to unpause - * - * @return Zero on success, non-zero on failure - */ -int ocre_container_unpause(struct ocre_container *container); - -/** - * @brief Gracefully stop a container - * @memberof ocre_container - * - * Stops a container in the context. The container must be in the RUNNING state, otherwise it will fail. - * - * The operation will signal the container to stop, and after a grace period, it will be forcefully terminated if not - * exited. - * - * Note: This is currently not supported in WAMR containers. - * - * @param container A pointer to the container to stop - * - * @return Zero on success, non-zero on failure - */ -int ocre_container_stop(struct ocre_container *container); - -/** - * @brief Forcefully terminate a container - * @memberof ocre_container - * - * Terminates a container in the context. The container must be in the RUNNING state, otherwise it will fail. - * - * @param container A pointer to the container to terminate - * - * @return Zero on success, non-zero on failure - */ -int ocre_container_kill(struct ocre_container *container); - -/** - * @brief Wait for a container to exit - * @memberof ocre_container - * - * If the container is STOPPED, returns the exit status of the container. - * - * If the container is RUNNING or PAUSED, waits for the container to exit. - * - * If the container is in other states, it will fail. - * - * @param container A pointer to the container to wait for - * @param[out] status A pointer to store the exit status of the container. Can be NULL - * - * @return Zero on success, non-zero on failure - */ -int ocre_container_wait(struct ocre_container *container, int *status); +#include +#include +#include #endif /* OCRE_H */ diff --git a/src/runtime/include/ocre/runtime/vtable.h b/src/runtime/include/ocre/runtime/vtable.h index 94dd5c9d..8f0b07ab 100644 --- a/src/runtime/include/ocre/runtime/vtable.h +++ b/src/runtime/include/ocre/runtime/vtable.h @@ -74,8 +74,8 @@ struct ocre_runtime_vtable { * * @return Pointer to the runtime context on success, NULL on failure */ - void *(*create)(const char *img_path, const char *workdir, const char **capabilities, - const char **argv, const char **envp, const char **mounts); + void *(*create)(const char *img_path, const char *workdir, const char **capabilities, const char **argv, + const char **envp, const char **mounts); /** * @brief Destroy a runtime instance From 3109fee625376dba92201191704c4b6aff498a85 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 22 Dec 2025 11:55:22 +0100 Subject: [PATCH 199/234] fix(wamr): do not free dir_map_list on create This is now required to be up when we start the container. So we keep the pointer in the context and free it on destroy. Signed-off-by: Marco Casaroli --- src/runtime/wamr/wamr.c | 74 ++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/src/runtime/wamr/wamr.c b/src/runtime/wamr/wamr.c index a05db2d5..fba3a25f 100644 --- a/src/runtime/wamr/wamr.c +++ b/src/runtime/wamr/wamr.c @@ -44,6 +44,8 @@ struct wamr_context { char **envp; bool uses_ocre_api; bool uses_shared_heap; + char **dir_map_list; + size_t dir_map_list_len; }; static int instance_execute(void *runtime_context, pthread_cond_t *cond) @@ -218,9 +220,9 @@ static void *instance_create(const char *img_path, const char *workdir, const ch const char **envp, const char **mounts) { struct wamr_context *context = NULL; - char **dir_map_list = NULL; + // char **dir_map_list = NULL; char **new_dir_map_list = NULL; - size_t dir_map_list_len = 0; + // size_t dir_map_list_len = 0; if (!img_path) { LOG_ERR("Invalid arguments"); @@ -328,26 +330,26 @@ static void *instance_create(const char *img_path, const char *workdir, const ch #endif #if CONFIG_OCRE_FILESYSTEM else if (!strcmp(*cap, "filesystem") && workdir) { - dir_map_list = malloc((dir_map_list_len + 2) * sizeof(char *)); - if (!dir_map_list) { + context->dir_map_list = malloc((context->dir_map_list_len + 2) * sizeof(char *)); + if (!context->dir_map_list) { LOG_ERR("Failed to allocate memory for dir_map_list"); goto error; } - memset(dir_map_list, 0, sizeof(char *)); + memset(context->dir_map_list, 0, sizeof(char *)); - dir_map_list[dir_map_list_len] = malloc(strlen("/::") + strlen(workdir) + 1); - if (!dir_map_list[dir_map_list_len]) { + context->dir_map_list[context->dir_map_list_len] = malloc(strlen("/::") + strlen(workdir) + 1); + if (!context->dir_map_list[context->dir_map_list_len]) { LOG_ERR("Failed to allocate memory for dir_map_list[0]"); - free(dir_map_list); + free(context->dir_map_list); goto error; } - sprintf(dir_map_list[dir_map_list_len], "/::%s", workdir); + sprintf(context->dir_map_list[context->dir_map_list_len], "/::%s", workdir); - dir_map_list_len++; + context->dir_map_list_len++; - dir_map_list[dir_map_list_len] = NULL; + context->dir_map_list[context->dir_map_list_len] = NULL; LOG_INF("Filesystem capability enabled"); } @@ -359,17 +361,17 @@ static void *instance_create(const char *img_path, const char *workdir, const ch for (const char **mount = mounts; mount && *mount; mount++) { /* Need to insert the extra ':' */ - new_dir_map_list = realloc(dir_map_list, (dir_map_list_len + 2) * sizeof(char *)); + new_dir_map_list = realloc(context->dir_map_list, (context->dir_map_list_len + 2) * sizeof(char *)); if (!new_dir_map_list) { LOG_ERR("Failed to allocate memory for dir_map_list"); goto error; } - dir_map_list = new_dir_map_list; + context->dir_map_list = new_dir_map_list; - dir_map_list[dir_map_list_len] = malloc(strlen(*mount) + 2); - if (!dir_map_list[dir_map_list_len]) { - LOG_ERR("Failed to allocate memory for dir_map_list[%zu]", dir_map_list_len); + context->dir_map_list[context->dir_map_list_len] = malloc(strlen(*mount) + 2); + if (!context->dir_map_list[context->dir_map_list_len]) { + LOG_ERR("Failed to allocate memory for dir_map_list[%zu]", context->dir_map_list_len); goto error; } @@ -379,9 +381,9 @@ static void *instance_create(const char *img_path, const char *workdir, const ch goto error; } - strcpy(dir_map_list[dir_map_list_len], *mount); + strcpy(context->dir_map_list[context->dir_map_list_len], *mount); - char *dst_colon = strchr(dir_map_list[dir_map_list_len], ':'); + char *dst_colon = strchr(context->dir_map_list[context->dir_map_list_len], ':'); if (!dst_colon) { LOG_ERR("Invalid mount format: %s", *mount); goto error; @@ -389,23 +391,17 @@ static void *instance_create(const char *img_path, const char *workdir, const ch sprintf(dst_colon + 1, ":%s", src_colon + 1); - LOG_INF("Enabled mount: %s", dir_map_list[dir_map_list_len]); + LOG_INF("Enabled mount: %s", context->dir_map_list[context->dir_map_list_len]); - dir_map_list_len++; + context->dir_map_list_len++; /* Add the NULL */ - dir_map_list[dir_map_list_len] = NULL; + context->dir_map_list[context->dir_map_list_len] = NULL; } - wasm_runtime_set_wasi_args(context->module, NULL, 0, (const char **)dir_map_list, dir_map_list_len, envp, envn, - context->argv, argc + 1); - - for (char **dir_map = dir_map_list; dir_map && *dir_map; dir_map++) { - free(*dir_map); - } - - free(dir_map_list); + wasm_runtime_set_wasi_args(context->module, NULL, 0, (const char **)context->dir_map_list, + context->dir_map_list_len, envp, envn, context->argv, argc + 1); return context; @@ -413,12 +409,6 @@ static void *instance_create(const char *img_path, const char *workdir, const ch wasm_runtime_unload(context->module); error: - for (char **dir_map = dir_map_list; dir_map && *dir_map; dir_map++) { - free(*dir_map); - } - - free(dir_map_list); - if (context) { if (context->module) { wasm_runtime_unload(context->module); @@ -429,6 +419,14 @@ static void *instance_create(const char *img_path, const char *workdir, const ch context->buffer = NULL; } + for (char **dir_map = context->dir_map_list; dir_map && *dir_map; dir_map++) { + free(*dir_map); + } + + free(context->dir_map_list); + + context->dir_map_list = NULL; + /* Only free what we allocated */ if (context->argv) { @@ -471,6 +469,12 @@ static int instance_destroy(void *runtime_context) } context->buffer = NULL; + for (char **dir_map = context->dir_map_list; dir_map && *dir_map; dir_map++) { + free(*dir_map); + } + + free(context->dir_map_list); + free(context->argv[0]); free(context->argv); From b6b5f4830f780029610a4c952f310b41215f4ef0 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 22 Dec 2025 12:27:18 +0100 Subject: [PATCH 200/234] chore(test): move hw tests to its own directory We will use the tests directory for system tests and unit tests. Signed-off-by: Marco Casaroli --- {tests => tests_hw}/README.md | 0 {tests => tests_hw}/beginTests.sh | 0 {tests => tests_hw}/groups/flashValidation/clean.sh | 0 {tests => tests_hw}/groups/flashValidation/config.json | 0 .../groups/flashValidation/flash_validation_hello_world.py | 0 {tests => tests_hw}/groups/flashValidation/setup.sh | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename {tests => tests_hw}/README.md (100%) rename {tests => tests_hw}/beginTests.sh (100%) rename {tests => tests_hw}/groups/flashValidation/clean.sh (100%) rename {tests => tests_hw}/groups/flashValidation/config.json (100%) rename {tests => tests_hw}/groups/flashValidation/flash_validation_hello_world.py (100%) rename {tests => tests_hw}/groups/flashValidation/setup.sh (100%) diff --git a/tests/README.md b/tests_hw/README.md similarity index 100% rename from tests/README.md rename to tests_hw/README.md diff --git a/tests/beginTests.sh b/tests_hw/beginTests.sh similarity index 100% rename from tests/beginTests.sh rename to tests_hw/beginTests.sh diff --git a/tests/groups/flashValidation/clean.sh b/tests_hw/groups/flashValidation/clean.sh similarity index 100% rename from tests/groups/flashValidation/clean.sh rename to tests_hw/groups/flashValidation/clean.sh diff --git a/tests/groups/flashValidation/config.json b/tests_hw/groups/flashValidation/config.json similarity index 100% rename from tests/groups/flashValidation/config.json rename to tests_hw/groups/flashValidation/config.json diff --git a/tests/groups/flashValidation/flash_validation_hello_world.py b/tests_hw/groups/flashValidation/flash_validation_hello_world.py similarity index 100% rename from tests/groups/flashValidation/flash_validation_hello_world.py rename to tests_hw/groups/flashValidation/flash_validation_hello_world.py diff --git a/tests/groups/flashValidation/setup.sh b/tests_hw/groups/flashValidation/setup.sh similarity index 100% rename from tests/groups/flashValidation/setup.sh rename to tests_hw/groups/flashValidation/setup.sh From 6102907add1fc424469cdf0cc297fa92f7a96d7a Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 22 Dec 2025 14:34:40 +0100 Subject: [PATCH 201/234] fix(container): stop: check for NULL before calling Since this function is optional in the runtime engine, we should check for existence and return error appropriately. Signed-off-by: Marco Casaroli --- src/ocre/container.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ocre/container.c b/src/ocre/container.c index 3a311ab4..d10eb625 100644 --- a/src/ocre/container.c +++ b/src/ocre/container.c @@ -473,6 +473,11 @@ int ocre_container_stop(struct ocre_container *container) goto unlock_mutex; } + if (!container->runtime->stop) { + LOG_ERR("Container '%s' does not support stop", container->id); + goto unlock_mutex; + } + LOG_INF("Sending stop signal to container '%s'", container->id); ret = container->runtime->stop(container->runtime_context); From c48aaecb6014e7995e08e8aca1b2f0b6d11a7315 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 22 Dec 2025 14:35:52 +0100 Subject: [PATCH 202/234] fix(demo): reduce wait Reduce the sleep time for demo. 4 seconds is enough for two messages. We want this to be fast, as we are using this for leak cheaks. Signed-off-by: Marco Casaroli --- src/samples/demo/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/samples/demo/main.c b/src/samples/demo/main.c index db5b055b..05b7a9de 100644 --- a/src/samples/demo/main.c +++ b/src/samples/demo/main.c @@ -118,7 +118,7 @@ int main(int argc, char *argv[]) return 1; } - sleep(8); + sleep(4); rc = ocre_container_kill(subscriber); if (rc) { From 289769ad02c3d6330befb832228c2824a6626e74 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 22 Dec 2025 14:37:28 +0100 Subject: [PATCH 203/234] build(demo): add run-demo make target To make it easier for development. Signed-off-by: Marco Casaroli --- src/samples/demo/posix/CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/samples/demo/posix/CMakeLists.txt b/src/samples/demo/posix/CMakeLists.txt index 619574de..a09a26f9 100644 --- a/src/samples/demo/posix/CMakeLists.txt +++ b/src/samples/demo/posix/CMakeLists.txt @@ -19,3 +19,10 @@ target_link_libraries(ocre_demo set(THREADS_PREFER_PTHREAD_FLAG TRUE) find_package(Threads) target_link_libraries(ocre_demo PRIVATE Threads::Threads) + +add_custom_target(run-demo + COMMAND pwd + COMMAND ${CMAKE_CURRENT_BINARY_DIR}/ocre_demo + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../.. + DEPENDS ocre_demo +) From 9cbe4ee107ab3f41b6fb52bbcbff1bee6adf9b38 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 22 Dec 2025 14:37:50 +0100 Subject: [PATCH 204/234] build(mini): add run-mini command To make it easier for development Signed-off-by: Marco Casaroli --- src/samples/mini/posix/CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/samples/mini/posix/CMakeLists.txt b/src/samples/mini/posix/CMakeLists.txt index d9d8bee4..1dee47a5 100644 --- a/src/samples/mini/posix/CMakeLists.txt +++ b/src/samples/mini/posix/CMakeLists.txt @@ -22,3 +22,10 @@ target_link_libraries(ocre_mini set(THREADS_PREFER_PTHREAD_FLAG TRUE) find_package(Threads) target_link_libraries(ocre_mini PRIVATE Threads::Threads) + +add_custom_target(run-mini + COMMAND pwd + COMMAND ${CMAKE_CURRENT_BINARY_DIR}/ocre_mini + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../.. + DEPENDS ocre_mini +) From bd82cc9635d217322eaf3787a08d38a317081cd5 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 22 Dec 2025 14:38:47 +0100 Subject: [PATCH 205/234] build: cleanup main makefile This should build ocre in Release mode by default. It should also honor any CMAKE_C_COMPILER/FLAGS, etc. passed to it. Signed-off-by: Marco Casaroli --- CMakeLists.txt | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5398cfaa..626c1c4f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,27 +5,16 @@ cmake_minimum_required(VERSION 3.20.0) -project(ocre LANGUAGES C ASM) - -set(CMAKE_BUILD_TYPE Debug) +project(ocre LANGUAGES C) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -set(CMAKE_VERBOSE_MAKEFILE ON) set(CMAKE_C_STANDARD 99) -set(CMAKE_CXX_STANDARD 17) set(WAMR_BUILD_PLATFORM linux) include (src/samples/demo/demo_containers.cmake) -# TODO move these to testing -list(APPEND OCRE_SDK_PRELOADED_IMAGES - "return0.wasm" - "return1.wasm" - "sleep_5_return_0.wasm" -) - # core add_subdirectory(src/ocre) add_subdirectory(src/runtime) @@ -44,5 +33,5 @@ add_subdirectory(src/shell) add_subdirectory(src/samples/mini/posix) add_subdirectory(src/samples/demo/posix) -# this sample is useful only for static code analysis on POSIX +# this sample is useful for static code analysis on POSIX add_subdirectory(src/samples/static_checks/posix) From 33ab86e71b341eccb01b3cd912306d13af4ce93b Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 22 Dec 2025 14:41:14 +0100 Subject: [PATCH 206/234] tests: add system tests System Tests by default handle Ocre Library as a black box. By default, they build ocre in Release mode as we want to test what we are delivering. We can also reuse them as part of source coverage generation and memory leak checks. This is why they should not tweak the build time variables, and allow us to override them, in case we want to use these tests. Signed-off-by: Marco Casaroli --- tests/system/container.c | 225 +++++++++++++ tests/system/context.c | 513 ++++++++++++++++++++++++++++++ tests/system/lib.c | 141 ++++++++ tests/system/ocre.c | 109 +++++++ tests/system/posix/CMakeLists.txt | 72 +++++ 5 files changed, 1060 insertions(+) create mode 100644 tests/system/container.c create mode 100644 tests/system/context.c create mode 100644 tests/system/lib.c create mode 100644 tests/system/ocre.c create mode 100644 tests/system/posix/CMakeLists.txt diff --git a/tests/system/container.c b/tests/system/container.c new file mode 100644 index 00000000..a5a79a82 --- /dev/null +++ b/tests/system/container.c @@ -0,0 +1,225 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include + +#include +#include + +struct ocre_context *context; +struct ocre_container *hello_world; +struct ocre_container *blinky; + +void setUp(void) +{ + const struct ocre_container_args args = { + .capabilities = + (const char *[]){ + "ocre:api", + NULL, + }, + }; + + ocre_initialize(NULL); + context = ocre_create_context("./ocre/src/ocre/var/lib/ocre"); + + hello_world = ocre_context_create_container(context, "hello-world.wasm", "wamr", "hello", false, NULL); + blinky = ocre_context_create_container(context, "blinky.wasm", "wamr", NULL, true, &args); +} + +void tearDown(void) +{ + ocre_container_kill(hello_world); + ocre_container_kill(blinky); + ocre_container_wait(hello_world, NULL); + ocre_container_wait(blinky, NULL); + ocre_context_remove_container(context, hello_world); + ocre_context_remove_container(context, blinky); + ocre_destroy_context(context); + ocre_deinitialize(); +} + +void test_ocre_container_status_null(void) +{ + TEST_ASSERT_EQUAL(OCRE_CONTAINER_STATUS_UNKNOWN, ocre_container_get_status(NULL)); +} + +void test_ocre_container_status(void) +{ + TEST_ASSERT_EQUAL(OCRE_CONTAINER_STATUS_CREATED, ocre_container_get_status(blinky)); + + /* Start blinky */ + + TEST_ASSERT_EQUAL_INT(0, ocre_container_start(blinky)); + TEST_ASSERT_EQUAL(OCRE_CONTAINER_STATUS_RUNNING, ocre_container_get_status(blinky)); + + /* Kill blinky */ + + TEST_ASSERT_EQUAL_INT(0, ocre_container_kill(blinky)); + + TEST_ASSERT_EQUAL_INT(0, ocre_container_wait(blinky, NULL)); + + TEST_ASSERT_EQUAL(OCRE_CONTAINER_STATUS_STOPPED, ocre_container_get_status(blinky)); +} + +void test_ocre_container_restart(void) +{ + TEST_ASSERT_EQUAL(OCRE_CONTAINER_STATUS_CREATED, ocre_container_get_status(hello_world)); + + /* Run hello_world */ + + TEST_ASSERT_EQUAL_INT(0, ocre_container_start(hello_world)); + TEST_ASSERT_EQUAL_INT(0, ocre_container_wait(hello_world, NULL)); + TEST_ASSERT_EQUAL(OCRE_CONTAINER_STATUS_STOPPED, ocre_container_get_status(hello_world)); + + /* Run again */ + + TEST_ASSERT_EQUAL_INT(0, ocre_container_start(hello_world)); + TEST_ASSERT_EQUAL_INT(0, ocre_container_wait(hello_world, NULL)); + TEST_ASSERT_EQUAL(OCRE_CONTAINER_STATUS_STOPPED, ocre_container_get_status(hello_world)); +} + +void test_ocre_container_kill(void) +{ + /* Run blinky */ + + TEST_ASSERT_EQUAL_INT(0, ocre_container_start(blinky)); + TEST_ASSERT_EQUAL(OCRE_CONTAINER_STATUS_RUNNING, ocre_container_get_status(blinky)); + + /* Kill blinky */ + + TEST_ASSERT_EQUAL_INT(0, ocre_container_kill(blinky)); + + /* Wait for blinky to stop */ + + int status; + TEST_ASSERT_EQUAL_INT(0, ocre_container_wait(blinky, &status)); + + /* Return code should indicate killed */ + // TODO: FIX!!! + TEST_ASSERT_EQUAL(0, status); + + /* Get status */ + + TEST_ASSERT_EQUAL(OCRE_CONTAINER_STATUS_STOPPED, ocre_container_get_status(blinky)); +} + +void test_ocre_container_destroy(void) +{ + /* Start blinky */ + + TEST_ASSERT_EQUAL_INT(0, ocre_container_start(blinky)); + + TEST_ASSERT_EQUAL(OCRE_CONTAINER_STATUS_RUNNING, ocre_container_get_status(blinky)); +} + +void test_ocre_container_get_image_null(void) +{ + TEST_ASSERT_NULL(ocre_container_get_image(NULL)); +} + +void test_ocre_container_get_image_blinky(void) +{ + TEST_ASSERT_EQUAL_STRING("blinky.wasm", ocre_container_get_image(blinky)); +} + +void test_ocre_container_get_id_null(void) +{ + TEST_ASSERT_NULL(ocre_container_get_id(NULL)); +} + +void test_ocre_container_get_id_hello(void) +{ + TEST_ASSERT_EQUAL_STRING("hello", ocre_container_get_id(hello_world)); +} + +void test_ocre_container_pause_unpause_null(void) +{ + TEST_ASSERT_EQUAL_INT(-1, ocre_container_pause(NULL)); + TEST_ASSERT_EQUAL_INT(-1, ocre_container_unpause(NULL)); +} + +void test_ocre_container_pause_unpause_wamr(void) +{ + /* Run blinky */ + + TEST_ASSERT_EQUAL_INT(0, ocre_container_start(blinky)); + TEST_ASSERT_EQUAL(OCRE_CONTAINER_STATUS_RUNNING, ocre_container_get_status(blinky)); + + /* Pause blinky. Does not work, will return -1 */ + + TEST_ASSERT_EQUAL_INT(-1, ocre_container_pause(blinky)); + + /* Should be running because pause does not work */ + TEST_ASSERT_EQUAL(OCRE_CONTAINER_STATUS_RUNNING, ocre_container_get_status(blinky)); + + /* Unpause blinky. Does not work, will return -1 */ + + TEST_ASSERT_EQUAL_INT(-1, ocre_container_unpause(blinky)); + + /* Should be running */ + TEST_ASSERT_EQUAL(OCRE_CONTAINER_STATUS_RUNNING, ocre_container_get_status(blinky)); + + /* Kill blinky */ + + TEST_ASSERT_EQUAL_INT(0, ocre_container_kill(blinky)); + + /* Wait for blinky to stop */ + + int status; + TEST_ASSERT_EQUAL_INT(0, ocre_container_wait(blinky, &status)); +} + +void test_ocre_container_stop_null(void) +{ + TEST_ASSERT_EQUAL_INT(-1, ocre_container_stop(NULL)); +} + +void test_ocre_container_stop_wamr(void) +{ + /* Run blinky */ + + TEST_ASSERT_EQUAL_INT(0, ocre_container_start(blinky)); + TEST_ASSERT_EQUAL(OCRE_CONTAINER_STATUS_RUNNING, ocre_container_get_status(blinky)); + + /* Stop blinky. Does not work, will return -1 */ + + TEST_ASSERT_EQUAL_INT(-1, ocre_container_stop(blinky)); + + /* Should be running because stop does not work */ + TEST_ASSERT_EQUAL(OCRE_CONTAINER_STATUS_RUNNING, ocre_container_get_status(blinky)); + + /* Kill blinky */ + + TEST_ASSERT_EQUAL_INT(0, ocre_container_kill(blinky)); + + /* Wait for blinky to stop */ + + int status; + TEST_ASSERT_EQUAL_INT(0, ocre_container_wait(blinky, &status)); +} + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_ocre_container_status_null); + RUN_TEST(test_ocre_container_status); + RUN_TEST(test_ocre_container_restart); + RUN_TEST(test_ocre_container_kill); + RUN_TEST(test_ocre_container_destroy); + RUN_TEST(test_ocre_container_get_image_null); + RUN_TEST(test_ocre_container_get_image_blinky); + RUN_TEST(test_ocre_container_get_id_null); + RUN_TEST(test_ocre_container_get_id_hello); + RUN_TEST(test_ocre_container_pause_unpause_null); + RUN_TEST(test_ocre_container_pause_unpause_wamr); + RUN_TEST(test_ocre_container_stop_null); + RUN_TEST(test_ocre_container_stop_wamr); + return UNITY_END(); +} diff --git a/tests/system/context.c b/tests/system/context.c new file mode 100644 index 00000000..bb34b2c6 --- /dev/null +++ b/tests/system/context.c @@ -0,0 +1,513 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include + +struct ocre_context *context; + +void setUp(void) +{ + ocre_initialize(NULL); + context = ocre_create_context("./ocre/src/ocre/var/lib/ocre"); +} + +void tearDown(void) +{ + ocre_destroy_context(context); + ocre_deinitialize(); +} + +void test_ocre_context_initialized(void) +{ + /* Context is initialized */ + + TEST_ASSERT_NOT_NULL(context); +} + +void test_ocre_context_get_working_directory_ok(void) +{ + /* Try to get working directory with good context */ + + TEST_ASSERT_NOT_NULL(ocre_context_get_working_directory(context)); +} + +void test_ocre_context_get_working_directory_err(void) +{ + /* Try to get working directory with bad context */ + + TEST_ASSERT_NULL(ocre_context_get_working_directory(NULL)); +} + +void test_ocre_context_create_container_null_context(void) +{ + /* Try to create container with bad context */ + + TEST_ASSERT_NULL(ocre_context_create_container(NULL, "hello-world.wasm", "wamr", NULL, false, NULL)); +} + +void test_ocre_context_create_container_bad_ids(void) +{ + /* Try to create container with bad ids */ + + TEST_ASSERT_NULL(ocre_context_create_container(context, NULL, NULL, NULL, false, NULL)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "", "", NULL, false, NULL)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr", ".", false, NULL)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr", "..", false, NULL)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr", "/", false, NULL)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr", "/somewhere", false, NULL)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr", "some/where", false, NULL)); + TEST_ASSERT_NULL(ocre_context_create_container(context, ".", "wamr", NULL, false, NULL)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "..", "wamr", NULL, false, NULL)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "/", "wamr", NULL, false, NULL)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "/somewhere", "wamr", NULL, false, NULL)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "some/where", "wamr", NULL, false, NULL)); +} + +void test_ocre_context_create_container_bad_runtimes(void) +{ + TEST_ASSERT_NULL( + ocre_context_create_container(context, "hello-world.wasm", "does-not-exit", NULL, false, NULL)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", NULL, NULL, false, NULL)); +} + +void test_ocre_context_create_container_bad_mounts(void) +{ + struct ocre_container_args bad_mounts = {0}; + + bad_mounts.mounts = (const char *[]){"no-colon", NULL}; + + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, &bad_mounts)); + + bad_mounts.mounts = (const char *[]){"no_abs_path:/hello", NULL}; + + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, &bad_mounts)); + + bad_mounts.mounts = (const char *[]){"/tmp:/", NULL}; + + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, &bad_mounts)); + + bad_mounts.mounts = (const char *[]){"/tmp:no_abs", NULL}; + + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, &bad_mounts)); + + bad_mounts.mounts = (const char *[]){"/tmp:", NULL}; + + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, &bad_mounts)); + + bad_mounts.mounts = (const char *[]){"/tmp", NULL}; + + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, &bad_mounts)); + + bad_mounts.mounts = (const char *[]){"/tmp:/ok", "bad", NULL}; + + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, &bad_mounts)); +} + +void test_ocre_context_remove_bad_container(void) +{ + /* Try to remove a non-existent container */ + + TEST_ASSERT_NOT_EQUAL_INT(0, ocre_context_remove_container(context, NULL)); +} + +void test_ocre_context_remove_bad_context(void) +{ + /* Try to remove containers from null context */ + + TEST_ASSERT_NOT_EQUAL_INT(0, ocre_context_remove_container(NULL, NULL)); +} + +void test_ocre_context_create_container_ok(void) +{ + /* Create a valid container */ + + struct ocre_container *container = + ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, NULL); + TEST_ASSERT_NOT_NULL(container); + + /* Check container status */ + + TEST_ASSERT_EQUAL_INT(OCRE_CONTAINER_STATUS_CREATED, ocre_container_get_status(container)); + + /* Remove the container */ + + TEST_ASSERT_EQUAL_INT(0, ocre_context_remove_container(context, container)); +} + +void test_ocre_context_create_container_with_id_ok(void) +{ + /* Create a valid container */ + + struct ocre_container *container = + ocre_context_create_container(context, "hello-world.wasm", "wamr", "test-container", false, NULL); + TEST_ASSERT_NOT_NULL(container); + + /* Check container status */ + + TEST_ASSERT_EQUAL_INT(OCRE_CONTAINER_STATUS_CREATED, ocre_container_get_status(container)); + + /* Check container id */ + + TEST_ASSERT_EQUAL_STRING("test-container", ocre_container_get_id(container)); + + /* Remove the container */ + + TEST_ASSERT_EQUAL_INT(0, ocre_context_remove_container(context, container)); +} + +void test_ocre_context_create_start_container_filesystem(void) +{ + const struct ocre_container_args args = { + .capabilities = + (const char *[]){ + "filesystem", + "ocre:api", + NULL, + }, + }; + + /* Create a valid container */ + + struct ocre_container *container = + ocre_context_create_container(context, "filesystem.wasm", "wamr", NULL, false, &args); + TEST_ASSERT_NOT_NULL(container); + + /* Start the container */ + + TEST_ASSERT_EQUAL_INT(0, ocre_container_start(container)); + + /* Remove the container */ + + TEST_ASSERT_EQUAL_INT(0, ocre_context_remove_container(context, container)); +} + +void test_ocre_context_create_container_with_id_twice(void) +{ + /* Create a valid container */ + + struct ocre_container *container = + ocre_context_create_container(context, "hello-world.wasm", "wamr", "test-container", false, NULL); + TEST_ASSERT_NOT_NULL(container); + + /* Another container with the same id should fail */ + + TEST_ASSERT_NULL( + ocre_context_create_container(context, "hello-world.wasm", "wamr", "test-container", false, NULL)); + + /* Remove the container */ + + TEST_ASSERT_EQUAL_INT(0, ocre_context_remove_container(context, container)); +} + +void test_ocre_context_create_container_and_forget(void) +{ + /* Create a valid container */ + + struct ocre_container *container = + ocre_context_create_container(context, "hello-world.wasm", "wamr", "should-not-leak", false, NULL); + TEST_ASSERT_NOT_NULL(container); + + /* Check container status */ + + TEST_ASSERT_EQUAL_INT(OCRE_CONTAINER_STATUS_CREATED, ocre_container_get_status(container)); + + /* Do not remove the container. When the context is destroyed, the container will be removed automatically */ +} + +void test_ocre_context_create_wait_remove(void) +{ + /* Create a valid container */ + + struct ocre_container *container = + ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, NULL); + TEST_ASSERT_NOT_NULL(container); + + /* Check container status */ + + TEST_ASSERT_EQUAL_INT(OCRE_CONTAINER_STATUS_CREATED, ocre_container_get_status(container)); + + /* Start the container */ + + TEST_ASSERT_EQUAL_INT(0, ocre_container_start(container)); + + /* Wait for the container to finish */ + + int status; + TEST_ASSERT_EQUAL_INT(0, ocre_container_wait(container, &status)); + + /* Check container status */ + + TEST_ASSERT_EQUAL_INT(0, status); + + /* Remove the container */ + + TEST_ASSERT_EQUAL_INT(0, ocre_context_remove_container(context, container)); +} + +void test_ocre_context_create_no_ocre_api(void) +{ + /* Create a valid container but it won't work as we don't have ocre:api */ + + struct ocre_container *container = + ocre_context_create_container(context, "blinky.wasm", "wamr", NULL, true, NULL); + TEST_ASSERT_NOT_NULL(container); + + /* Check container status */ + + TEST_ASSERT_EQUAL_INT(OCRE_CONTAINER_STATUS_CREATED, ocre_container_get_status(container)); + + /* Start the container */ + + TEST_ASSERT_EQUAL_INT(0, ocre_container_start(container)); + + /* Wait for the container to finish */ + + int status; + TEST_ASSERT_EQUAL_INT(0, ocre_container_wait(container, &status)); + + /* Check container status */ + // TODO: Maybe this should be error? + + TEST_ASSERT_EQUAL_INT(OCRE_CONTAINER_STATUS_STOPPED, ocre_container_get_status(container)); + + /* Check return status */ + + TEST_ASSERT_EQUAL_INT(-1, status); + + /* Cannot kill stopped container */ + + TEST_ASSERT_EQUAL_INT(-1, ocre_container_kill(container)); + + /* Remove the container */ + + TEST_ASSERT_EQUAL_INT(0, ocre_context_remove_container(context, container)); +} + +void test_ocre_context_create_kill_wait_remove(void) +{ + const struct ocre_container_args args = { + .capabilities = + (const char *[]){ + "ocre:api", + NULL, + }, + }; + + /* Create a valid container and have ocre:api*/ + + struct ocre_container *container = + ocre_context_create_container(context, "blinky.wasm", "wamr", NULL, true, &args); + TEST_ASSERT_NOT_NULL(container); + + /* Check container status */ + + TEST_ASSERT_EQUAL_INT(OCRE_CONTAINER_STATUS_CREATED, ocre_container_get_status(container)); + + /* Start the container */ + + TEST_ASSERT_EQUAL_INT(0, ocre_container_start(container)); + + /* Check container status */ + TEST_ASSERT_EQUAL_INT(OCRE_CONTAINER_STATUS_RUNNING, ocre_container_get_status(container)); + + /* Kill the container */ + + TEST_ASSERT_EQUAL_INT(0, ocre_container_kill(container)); + + /* Wait for the container to finish */ + + int status; + TEST_ASSERT_EQUAL_INT(0, ocre_container_wait(container, &status)); + + /* Check container status */ + + TEST_ASSERT_EQUAL_INT(OCRE_CONTAINER_STATUS_STOPPED, ocre_container_get_status(container)); + + /* Check return status */ + // TODO: Maybe this should not be 0 + + TEST_ASSERT_EQUAL_INT(0, status); + + /* Remove the container */ + + TEST_ASSERT_EQUAL_INT(0, ocre_context_remove_container(context, container)); +} + +void test_ocre_context_get_container_count_null(void) +{ + /* There must be zero containers */ + + TEST_ASSERT_EQUAL_INT(-1, ocre_context_get_container_count(NULL)); +} + +void test_ocre_context_get_container_count(void) +{ + /* There must be zero containers */ + + TEST_ASSERT_EQUAL_INT(0, ocre_context_get_container_count(context)); + + /* Create a valid container */ + + struct ocre_container *container1 = + ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, NULL); + TEST_ASSERT_NOT_NULL(container1); + + /* There must be one container */ + + TEST_ASSERT_EQUAL_INT(1, ocre_context_get_container_count(context)); + + /* Create another valid container */ + + struct ocre_container *container2 = + ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, NULL); + TEST_ASSERT_NOT_NULL(container2); + + /* There must be two containers */ + + TEST_ASSERT_EQUAL_INT(2, ocre_context_get_container_count(context)); + + /* Remove the container */ + + TEST_ASSERT_EQUAL_INT(0, ocre_context_remove_container(context, container1)); + + /* There must be one container */ + + TEST_ASSERT_EQUAL_INT(1, ocre_context_get_container_count(context)); + + /* Remove the container */ + + TEST_ASSERT_EQUAL_INT(0, ocre_context_remove_container(context, container2)); + + /* There must be zero containers */ + + TEST_ASSERT_EQUAL_INT(0, ocre_context_get_container_count(context)); +} + +void test_ocre_context_get_container_by_id_error(void) +{ + TEST_ASSERT_NULL(ocre_context_get_container_by_id(context, "bad_id")); + TEST_ASSERT_NULL(ocre_context_get_container_by_id(context, NULL)); + TEST_ASSERT_NULL(ocre_context_get_container_by_id(NULL, "bad_id")); + TEST_ASSERT_NULL(ocre_context_get_container_by_id(NULL, NULL)); +} + +void test_ocre_context_get_container_by_id_ok(void) +{ + /* Create a valid container */ + + struct ocre_container *container = + ocre_context_create_container(context, "hello-world.wasm", "wamr", "my-id", false, NULL); + TEST_ASSERT_NOT_NULL(container); + + /* Get container by ID */ + + TEST_ASSERT_EQUAL_PTR(container, ocre_context_get_container_by_id(context, "my-id")); + + /* Remove the container */ + + TEST_ASSERT_EQUAL_INT(0, ocre_context_remove_container(context, container)); +} + +void test_ocre_context_get_containers_err(void) +{ + struct ocre_container *containers[1]; + TEST_ASSERT_EQUAL_INT(-1, ocre_context_get_containers(context, NULL, 0)); + TEST_ASSERT_EQUAL_INT(-1, ocre_context_get_containers(context, NULL, 1)); + TEST_ASSERT_EQUAL_INT(-1, ocre_context_get_containers(NULL, NULL, 0)); + TEST_ASSERT_EQUAL_INT(-1, ocre_context_get_containers(NULL, NULL, 1)); + TEST_ASSERT_EQUAL_INT(-1, ocre_context_get_containers(NULL, containers, 0)); + TEST_ASSERT_EQUAL_INT(-1, ocre_context_get_containers(NULL, containers, 1)); +} + +void test_ocre_context_get_containers_zero(void) +{ + struct ocre_container *containers[1]; + TEST_ASSERT_EQUAL_INT(0, ocre_context_get_containers(context, containers, 0)); + TEST_ASSERT_EQUAL_INT(0, ocre_context_get_containers(context, containers, 1)); +} + +void test_ocre_context_get_containers_ok(void) +{ + struct ocre_container *containers[2]; + + /* Create a valid container */ + + struct ocre_container *container1 = + ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, NULL); + TEST_ASSERT_NOT_NULL(container1); + + /* There must be one container */ + + TEST_ASSERT_EQUAL_INT(1, ocre_context_get_containers(context, containers, 2)); + + /* Create another valid container */ + + struct ocre_container *container2 = + ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, NULL); + TEST_ASSERT_NOT_NULL(container2); + + /* There must be two containers */ + + TEST_ASSERT_EQUAL_INT(2, ocre_context_get_containers(context, containers, 2)); + + /* We request only one */ + + TEST_ASSERT_EQUAL_INT(1, ocre_context_get_containers(context, containers, 1)); + + /* We request zero */ + + TEST_ASSERT_EQUAL_INT(0, ocre_context_get_containers(context, containers, 0)); + + /* Remove the container */ + + TEST_ASSERT_EQUAL_INT(0, ocre_context_remove_container(context, container1)); + + /* There must be one container */ + + TEST_ASSERT_EQUAL_INT(1, ocre_context_get_containers(context, containers, 2)); + + /* Remove the container */ + + TEST_ASSERT_EQUAL_INT(0, ocre_context_remove_container(context, container2)); + + /* There must be one container */ + + TEST_ASSERT_EQUAL_INT(0, ocre_context_get_containers(context, containers, 2)); +} + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_ocre_context_initialized); + RUN_TEST(test_ocre_context_get_working_directory_ok); + RUN_TEST(test_ocre_context_get_working_directory_err); + RUN_TEST(test_ocre_context_create_container_null_context); + RUN_TEST(test_ocre_context_create_container_bad_ids); + RUN_TEST(test_ocre_context_create_container_bad_runtimes); + RUN_TEST(test_ocre_context_create_container_bad_mounts); + RUN_TEST(test_ocre_context_remove_bad_container); + RUN_TEST(test_ocre_context_remove_bad_context); + RUN_TEST(test_ocre_context_create_container_ok); + RUN_TEST(test_ocre_context_create_container_with_id_ok); + RUN_TEST(test_ocre_context_create_container_with_id_twice); + RUN_TEST(test_ocre_context_create_container_and_forget); + RUN_TEST(test_ocre_context_create_wait_remove); + RUN_TEST(test_ocre_context_create_no_ocre_api); + RUN_TEST(test_ocre_context_create_kill_wait_remove); + RUN_TEST(test_ocre_context_create_start_container_filesystem); + RUN_TEST(test_ocre_context_get_container_count); + RUN_TEST(test_ocre_context_get_container_count_null); + RUN_TEST(test_ocre_context_get_container_by_id_error); + RUN_TEST(test_ocre_context_get_container_by_id_ok); + RUN_TEST(test_ocre_context_get_containers_err); + RUN_TEST(test_ocre_context_get_containers_zero); + RUN_TEST(test_ocre_context_get_containers_ok); + return UNITY_END(); +} diff --git a/tests/system/lib.c b/tests/system/lib.c new file mode 100644 index 00000000..3245acf9 --- /dev/null +++ b/tests/system/lib.c @@ -0,0 +1,141 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +void test_ocre_build_config(void) +{ + TEST_ASSERT_NOT_NULL(ocre_build_configuration.version); + TEST_ASSERT_NOT_NULL(ocre_build_configuration.commit_id); + TEST_ASSERT_NOT_NULL(ocre_build_configuration.build_info); + TEST_ASSERT_NOT_NULL(ocre_build_configuration.build_date); +} + +void test_ocre_initialize_null(void) +{ + /* Initialize ocre should work */ + + TEST_ASSERT_EQUAL_INT(0, ocre_initialize(NULL)); + + ocre_deinitialize(); +} + +void test_ocre_initialize_arr_null(void) +{ + /* Initialize ocre with a NULL array should work */ + + TEST_ASSERT_EQUAL_INT(0, ocre_initialize((const struct ocre_runtime_vtable *const[]){NULL})); + + ocre_deinitialize(); +} + +static int dummy_runtime_init_ok(void) +{ + return 0; +} + +const struct ocre_runtime_vtable test_runtime_ok = { + .runtime_name = "test", + .init = dummy_runtime_init_ok, +}; + +void test_ocre_initialize_vtable_init_ok(void) +{ + /* Initialize ocre with a good vtable should call init on the runtime */ + + TEST_ASSERT_EQUAL_INT(0, ocre_initialize((const struct ocre_runtime_vtable *const[]){ + &test_runtime_ok, + NULL, + })); + + ocre_deinitialize(); +} + +static int dummy_runtime_init_err(void) +{ + return -1; +} + +const struct ocre_runtime_vtable test_runtime_err = { + .runtime_name = "test", + .init = dummy_runtime_init_err, +}; + +void test_ocre_initialize_vtable_init_err(void) +{ + /* Initialize ocre with a good vtable should call init on the runtime but it fails */ + + TEST_ASSERT_NOT_EQUAL_INT(0, ocre_initialize((const struct ocre_runtime_vtable *const[]){ + &test_runtime_err, + NULL, + })); +} + +void test_ocre_initialize_duplicate(void) +{ + /* Try to initialize ocre with two runtimes with the same name should fail */ + + TEST_ASSERT_NOT_EQUAL_INT(0, ocre_initialize((const struct ocre_runtime_vtable *const[]){ + &test_runtime_ok, + &test_runtime_ok, + NULL, + })); +} + +static int dummy_runtime_init_func(void) +{ + /* We just deinit here and pass the test */ + + ocre_deinitialize(); + + TEST_PASS(); + + return 0; +} + +const struct ocre_runtime_vtable dummy_runtime = { + .runtime_name = "dummy", + .init = dummy_runtime_init_func, +}; + +void test_ocre_initialize_init_called(void) +{ + /* Initialize ocre with two runtimes with the same name should fail */ + + ocre_initialize((const struct ocre_runtime_vtable *const[]){ + &dummy_runtime, + NULL, + }); + + /* If we reach here, we failed to run the init function */ + + TEST_FAIL(); +} + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_ocre_build_config); + RUN_TEST(test_ocre_initialize_null); + RUN_TEST(test_ocre_initialize_arr_null); + RUN_TEST(test_ocre_initialize_vtable_init_ok); + RUN_TEST(test_ocre_initialize_vtable_init_err); + RUN_TEST(test_ocre_initialize_duplicate); + RUN_TEST(test_ocre_initialize_init_called); + return UNITY_END(); +} diff --git a/tests/system/ocre.c b/tests/system/ocre.c new file mode 100644 index 00000000..3e57b6d3 --- /dev/null +++ b/tests/system/ocre.c @@ -0,0 +1,109 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include + +void setUp(void) +{ + ocre_initialize(NULL); +} + +void tearDown(void) +{ + ocre_deinitialize(); +} + +void test_ocre_create_default_context(void) +{ + /* Creating the main context should work */ + + struct ocre_context *main_ctx = ocre_create_context(NULL); + TEST_ASSERT_NOT_NULL(main_ctx); + + /* We can also destroy the main_ctx */ + + TEST_ASSERT_EQUAL_INT(0, ocre_destroy_context(main_ctx)); +} + +void test_ocre_create_provided_context(void) +{ + /* Creating the other context should work */ + + struct ocre_context *other_ctx = ocre_create_context("othercontext"); + TEST_ASSERT_NOT_NULL(other_ctx); + + /* We can also destroy the other context */ + + TEST_ASSERT_EQUAL_INT(0, ocre_destroy_context(other_ctx)); +} + +void test_ocre_create_two_contexts(void) +{ + /* Creating the main context should work */ + + struct ocre_context *main_ctx = ocre_create_context(NULL); + TEST_ASSERT_NOT_NULL(main_ctx); + + /* Creating the other context should work */ + + struct ocre_context *other_ctx = ocre_create_context("othercontext"); + TEST_ASSERT_NOT_NULL(other_ctx); + + /* We can also destroy the main_ctx */ + + TEST_ASSERT_EQUAL_INT(0, ocre_destroy_context(main_ctx)); + + /* We can also destroy the other context */ + + TEST_ASSERT_EQUAL_INT(0, ocre_destroy_context(other_ctx)); +} + +void test_ocre_create_context_twice(void) +{ + /* Creating the context once should work */ + + struct ocre_context *main_ctx = ocre_create_context(NULL); + TEST_ASSERT_NOT_NULL(main_ctx); + + /* Trying to create another context with the same workdir should fail */ + + TEST_ASSERT_NULL(ocre_create_context(NULL)); + + /* We can also destroy the main_ctx */ + + TEST_ASSERT_EQUAL_INT(0, ocre_destroy_context(main_ctx)); +} + +void test_ocre_create_context_no_cleanup(void) +{ + /* Creating the context once should work */ + + struct ocre_context *main_ctx = ocre_create_context(NULL); + TEST_ASSERT_NOT_NULL(main_ctx); + + /* Do not cleanup the context. ocre_deinitialize() should do it for us */ +} + +void test_ocre_destroy_null_context(void) +{ + TEST_ASSERT_NOT_EQUAL_INT(0, ocre_destroy_context(NULL)); +} + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_ocre_create_default_context); + RUN_TEST(test_ocre_create_provided_context); + RUN_TEST(test_ocre_create_two_contexts); + RUN_TEST(test_ocre_create_context_twice); + RUN_TEST(test_ocre_create_context_no_cleanup); + RUN_TEST(test_ocre_destroy_null_context); + return UNITY_END(); +} diff --git a/tests/system/posix/CMakeLists.txt b/tests/system/posix/CMakeLists.txt new file mode 100644 index 00000000..ff2905a1 --- /dev/null +++ b/tests/system/posix/CMakeLists.txt @@ -0,0 +1,72 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +set(CMAKE_C_COMPILER /usr/bin/clang) + +list(APPEND OCRE_SDK_PRELOADED_IMAGES + "return0.wasm" + "return1.wasm" + "sleep_5_return_0.wasm" +) + +if (SANITIZER) + string(APPEND CMAKE_C_FLAGS + "-fsanitize=address" +) +endif() + +project(OcreSystemTestPosix) + +add_subdirectory(../../.. ocre) + +add_library(Unity STATIC + ../../Unity/src/Unity.c +) + +target_include_directories(Unity PUBLIC + ../../Unity/src +) + +list(APPEND OCRE_TESTS + lib + ocre + context + container +) + +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/ocre/var/lib/ocre/images) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/ocre/var/lib/ocre/containers) + +foreach(test ${OCRE_TESTS}) + add_executable(test_${test} + ../${test}.c + ) + + target_link_libraries(test_${test} + OcreCore + Unity + ) + + add_custom_command( + OUTPUT test_${test}.log + COMMAND LLVM_PROFILE_FILE=test_${test}.profraw ./test_${test} > test_${test}.log + COMMAND rm -f test_${test}.testpass test_${test}.testfail + COMMAND sh -c "[ \"$(tail -1 test_${test}.log)\" = \"OK\" ] && cp test_${test}.log test_${test}.testpass || cp test_${test}.log test_${test}.testfail" + DEPENDS + test_${test} + VERBATIM + ) +endforeach() + +add_custom_target(run-systests + COMMAND python ${CMAKE_CURRENT_LIST_DIR}/../../Unity/auto/unity_test_summary.py ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS + test_lib.log + test_ocre.log + test_context.log + test_container.log +) From de251e22761f95c59f372f8c3f8904da54786733 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 22 Dec 2025 14:44:47 +0100 Subject: [PATCH 207/234] build: memory leaks checker We build ocre with clang address sanitizer, then execute mini, demo and the system tests. Signed-off-by: Marco Casaroli --- tests/leaks/CMakeLists.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 tests/leaks/CMakeLists.txt diff --git a/tests/leaks/CMakeLists.txt b/tests/leaks/CMakeLists.txt new file mode 100644 index 00000000..306cd0b1 --- /dev/null +++ b/tests/leaks/CMakeLists.txt @@ -0,0 +1,20 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +set(CMAKE_C_COMPILER /usr/bin/clang) + +string(APPEND CMAKE_C_FLAGS + "-fsanitize=address" +) + +project(OcreLeaksCheckPosix) + +add_subdirectory(../system/posix OcreSystemTests) + +add_custom_target(always_run ALL + DEPENDS run-systests run-demo run-mini +) From dab66db0fb9e3bbdce2312e7287b464e331f768e Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 22 Dec 2025 14:47:09 +0100 Subject: [PATCH 208/234] build: source code test coverage We build the system tests with instrumentation, so we can generate the coverage report. Signed-off-by: Marco Casaroli --- tests/coverage/CMakeLists.txt | 36 +++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 tests/coverage/CMakeLists.txt diff --git a/tests/coverage/CMakeLists.txt b/tests/coverage/CMakeLists.txt new file mode 100644 index 00000000..daf29918 --- /dev/null +++ b/tests/coverage/CMakeLists.txt @@ -0,0 +1,36 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +set(CMAKE_C_COMPILER /usr/bin/clang) + +set(CMAKE_C_FLAGS + "-fprofile-instr-generate -fcoverage-mapping" +) + +project(OcreTestSourceCoverage) + +add_subdirectory(../system/posix OcreSystemTests) + +add_custom_target(coverage ALL + COMMAND llvm-profdata merge -sparse + OcreSystemTests/test_lib.profraw + OcreSystemTests/test_ocre.profraw + OcreSystemTests/test_context.profraw + OcreSystemTests/test_container.profraw + -o default.profdata + COMMAND llvm-cov show + -format=html -output-dir=report + -instr-profile=default.profdata + --ignore-filename-regex=$wasm-micro-runtime/ + --ignore-filename-regex=$test/ + --object=OcreSystemTests/test_lib + --object=OcreSystemTests/test_ocre + --object=OcreSystemTests/test_context + --object=OcreSystemTests/test_container + DEPENDS + run-systests +) From b658dff1dffb6b0637ef81183c5754d9e645caec Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 22 Dec 2025 14:55:51 +0100 Subject: [PATCH 209/234] ci: run tests in CI We now run the system tests, leak checks and coverage report generation in the CI. Signed-off-by: Marco Casaroli --- .github/workflows/linux.yml | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 56fa782d..5ba88e7c 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -26,6 +26,47 @@ jobs: with: submodules: true + - name: Configure (system tests) + run: mkdir build && cd build && cmake ../tests/system/posix + + - name: Build (system tests) + working-directory: build + run: make + + - name: Run (system tests) + working-directory: build + run: make run-systests + + - name: Delete build directory + run: rm -rf build + + - name: Configure (leak checks) + run: mkdir build && cd build && cmake ../tests/leaks + + - name: Build and run (leak checks) + working-directory: build + run: make + + - name: Delete build directory + run: rm -rf build + + - name: Configure (source coverage) + run: mkdir build && cd build && cmake ../tests/coverage + + - name: Build and run (source coverage) + working-directory: build + run: make + + - name: Upload coverage report + uses: actions/upload-artifact@v4 + with: + name: ocre-coverage + include-hidden-files: true + path: build/report + + - name: Delete build directory + run: rm -rf build + - name: Configure run: mkdir build && cd build && cmake .. From 221ed571f70bc85b2e224233b5f8ff1acf093f1b Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 22 Dec 2025 15:00:38 +0100 Subject: [PATCH 210/234] test: add Unity test system We will use them for our system tests and unit tests. Signed-off-by: Marco Casaroli --- .gitmodules | 3 +++ tests/Unity | 1 + 2 files changed, 4 insertions(+) create mode 160000 tests/Unity diff --git a/.gitmodules b/.gitmodules index ec8157c2..6ac55962 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,3 +5,6 @@ [submodule "ocre-sdk"] path = ocre-sdk url = https://github.com/project-ocre/ocre-sdk.git +[submodule "tests/Unity"] + path = tests/Unity + url = https://github.com/ThrowTheSwitch/Unity.git diff --git a/tests/Unity b/tests/Unity new file mode 160000 index 00000000..cbcd08fa --- /dev/null +++ b/tests/Unity @@ -0,0 +1 @@ +Subproject commit cbcd08fa7de711053a3deec6339ee89cad5d2697 From e1316e60778a9c8dae4e1909a91fce91fb767fff Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 22 Dec 2025 15:13:21 +0100 Subject: [PATCH 211/234] build(unity): typo For case sentive filesystems Signed-off-by: Marco Casaroli --- tests/system/posix/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/system/posix/CMakeLists.txt b/tests/system/posix/CMakeLists.txt index ff2905a1..6c3aaf54 100644 --- a/tests/system/posix/CMakeLists.txt +++ b/tests/system/posix/CMakeLists.txt @@ -24,7 +24,7 @@ project(OcreSystemTestPosix) add_subdirectory(../../.. ocre) add_library(Unity STATIC - ../../Unity/src/Unity.c + ../../Unity/src/unity.c ) target_include_directories(Unity PUBLIC From f36334f6da29984cb94d8be42843c6ed8b49dfc6 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 22 Dec 2025 17:59:34 +0100 Subject: [PATCH 212/234] ci: use self-hosted runners Signed-off-by: Marco Casaroli --- .github/workflows/devcontainer-linux.yml | 4 ++-- .github/workflows/devcontainer-zephyr.yml | 4 ++-- .github/workflows/formatting-checks.yml | 3 ++- .github/workflows/linux.yml | 3 ++- .github/workflows/zephyr.yml | 3 ++- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/devcontainer-linux.yml b/.github/workflows/devcontainer-linux.yml index 57670dba..2cac4af0 100644 --- a/.github/workflows/devcontainer-linux.yml +++ b/.github/workflows/devcontainer-linux.yml @@ -14,7 +14,7 @@ on: jobs: necessary: name: Necessary? - runs-on: ubuntu-24.04 + runs-on: self-hosted outputs: build: ${{ steps.changed-files.outputs.all_changed_and_modified_files != '' }} devcontainer-tag: ${{ steps.devcontainer-tag.outputs.tag }} @@ -42,7 +42,7 @@ jobs: if: ${{ needs.necessary.outputs.build == 'true' }} needs: - necessary - runs-on: ubuntu-24.04 + runs-on: self-hosted steps: - name: Checkout the code diff --git a/.github/workflows/devcontainer-zephyr.yml b/.github/workflows/devcontainer-zephyr.yml index 245ed080..75af42cd 100644 --- a/.github/workflows/devcontainer-zephyr.yml +++ b/.github/workflows/devcontainer-zephyr.yml @@ -14,7 +14,7 @@ on: jobs: necessary: name: Necessary? - runs-on: ubuntu-24.04 + runs-on: self-hosted outputs: build: ${{ steps.changed-files.outputs.all_changed_and_modified_files != '' }} devcontainer-tag: ${{ steps.devcontainer-tag.outputs.tag }} @@ -44,7 +44,7 @@ jobs: if: ${{ needs.necessary.outputs.build == 'true' }} needs: - necessary - runs-on: ubuntu-24.04 + runs-on: self-hosted steps: - name: Checkout the code diff --git a/.github/workflows/formatting-checks.yml b/.github/workflows/formatting-checks.yml index 551f4ead..9fd74799 100644 --- a/.github/workflows/formatting-checks.yml +++ b/.github/workflows/formatting-checks.yml @@ -17,9 +17,10 @@ on: jobs: format-checks: name: Formatting checks - runs-on: ubuntu-latest + runs-on: self-hosted container: image: ghcr.io/${{ github.repository }}/devcontainer-linux:${{ inputs.devcontainer-tag }} + options: --user 1000:1000 steps: - name: checkout uses: actions/checkout@v5 diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 5ba88e7c..126ab9ce 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -17,9 +17,10 @@ on: jobs: build-linux: name: Linux build - runs-on: ubuntu-latest + runs-on: self-hosted container: image: ghcr.io/${{ github.repository }}/devcontainer-linux:${{ inputs.devcontainer-tag }} + options: --user 1000:1000 steps: - name: Checkout uses: actions/checkout@v4 diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index 77852fc4..9d12b6fe 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -17,9 +17,10 @@ on: jobs: build-zephyr: name: Zephyr build - runs-on: ubuntu-latest + runs-on: self-hosted container: image: ghcr.io/${{ github.repository }}/devcontainer-zephyr:${{ inputs.devcontainer-tag }} + options: --user 1000:1000 strategy: matrix: board: From b2310095bc29bd0a1e62e3ac108c9b0af468f9ac Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 22 Dec 2025 18:19:17 +0100 Subject: [PATCH 213/234] ci(decontaier): add clang address sanitizer libs Signed-off-by: Marco Casaroli --- .devcontainer/linux/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/.devcontainer/linux/Dockerfile b/.devcontainer/linux/Dockerfile index 025432d2..e169c9bd 100644 --- a/.devcontainer/linux/Dockerfile +++ b/.devcontainer/linux/Dockerfile @@ -22,6 +22,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ clang \ clang-format \ clang-tools \ + libclang-rt-dev \ llvm \ net-tools \ jq \ From 1b20d4cb780f5cdd6b0b6a92903bb85b058fed32 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 22 Dec 2025 19:30:33 +0100 Subject: [PATCH 214/234] ci: improve devcontainer Signed-off-by: Marco Casaroli --- .devcontainer/.DS_Store | Bin 0 -> 6148 bytes .devcontainer/linux/Dockerfile | 10 +++--- .devcontainer/linux/devcontainer.json | 9 +++-- .devcontainer/zephyr/Dockerfile | 41 +++++++++++----------- .devcontainer/zephyr/devcontainer.json | 12 +++++-- .github/workflows/devcontainer-linux.yml | 4 +-- .github/workflows/devcontainer-zephyr.yml | 4 +-- .github/workflows/formatting-checks.yml | 1 - .github/workflows/linux.yml | 1 - .github/workflows/zephyr.yml | 5 +-- 10 files changed, 45 insertions(+), 42 deletions(-) create mode 100644 .devcontainer/.DS_Store diff --git a/.devcontainer/.DS_Store b/.devcontainer/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..1ba0d2bfd4b44cee8a12dfed1e049be296b77620 GIT binary patch literal 6148 zcmeHKJ5Iwu5SiApg@!9|0t&9co1IaJ zokVm9!HhKf*7I4f-&!6I5%G929T5$QD1i$04l!&I@r!Oq&n)8PxW=-$9p%?mS#QL; z;de41XSYuU&FPL7)H%PwN84LgSvD!E39QN6{P{g!zMOU=rr$)=v-LM5Ae{#ENHhNU2^1wutpET3 literal 0 HcmV?d00001 diff --git a/.devcontainer/linux/Dockerfile b/.devcontainer/linux/Dockerfile index e169c9bd..fe17ccf4 100644 --- a/.devcontainer/linux/Dockerfile +++ b/.devcontainer/linux/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:24.04 +FROM ubuntu:24.04 AS ocre-ci ARG USERNAME=ocre-dev ARG USER_UID=1000 @@ -25,6 +25,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libclang-rt-dev \ llvm \ net-tools \ + sudo \ jq \ && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \ echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list && \ @@ -38,14 +39,15 @@ RUN mkdir /opt/wasi-sdk && \ curl -sSL https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-$WASI_SDK_VERSION/wasi-sdk-$WASI_SDK_VERSION.0-$(uname -m | sed s/aarch64/arm64/)-linux.tar.gz | \ tar zxvf - --strip-components=1 -C /opt/wasi-sdk +FROM ocre-ci AS ocre-dev + # Accomodate the user for devcontainer RUN (userdel -r $USERNAME ; userdel -r `id -nu $USER_UID` ; groupdel `id -ng $USER_GID`) || true \ && groupadd --gid $USER_GID $USERNAME \ && useradd --uid $USER_UID --gid $USER_GID -m $USERNAME -s /bin/bash \ - && apt-get update \ - && apt-get install -y sudo \ && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \ && chmod 0440 /etc/sudoers.d/$USERNAME USER $USERNAME -WORKDIR /home/ocre-dev + +WORKDIR /home/$USERNAME diff --git a/.devcontainer/linux/devcontainer.json b/.devcontainer/linux/devcontainer.json index 81a64255..95dad25b 100644 --- a/.devcontainer/linux/devcontainer.json +++ b/.devcontainer/linux/devcontainer.json @@ -1,6 +1,11 @@ { "build": { - "dockerfile": "Dockerfile" + "dockerfile": "Dockerfile", + "args": { + "USERNAME": "${localEnv:USER}", + "USER_UID": "${localEnv:REMOTE_UID:1000}", + "USER_GID": "${localEnv:REMOTE_GID:1000}" + } }, - "remoteUser": "ocre-dev" + "remoteUser": "${localEnv:USER}" } diff --git a/.devcontainer/zephyr/Dockerfile b/.devcontainer/zephyr/Dockerfile index 9664529e..f3a695e4 100644 --- a/.devcontainer/zephyr/Dockerfile +++ b/.devcontainer/zephyr/Dockerfile @@ -36,6 +36,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python3-dev \ python3-venv \ python3-tk \ + sudo \ wget \ xz-utils \ && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \ @@ -50,21 +51,8 @@ RUN mkdir /opt/wasi-sdk && \ curl -sSL https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-$WASI_SDK_VERSION/wasi-sdk-$WASI_SDK_VERSION.0-$(uname -m | sed s/aarch64/arm64/)-linux.tar.gz | \ tar zxvf - --strip-components=1 -C /opt/wasi-sdk -# Accomodate the user for devcontainer -RUN (userdel -r $USERNAME ; userdel -r `id -nu $USER_UID` ; groupdel `id -ng $USER_GID`) || true \ - && groupadd --gid $USER_GID $USERNAME \ - && useradd --uid $USER_UID --gid $USER_GID -m $USERNAME -s /bin/bash \ - && apt-get update \ - && apt-get install -y sudo \ - && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \ - && chmod 0440 /etc/sudoers.d/$USERNAME - -USER $USERNAME - -WORKDIR /home/ocre-dev - -RUN python -m venv .venv && \ - . .venv/bin/activate && \ +RUN python -m venv /opt/zephyr-venv && \ + . /opt/zephyr-venv/bin/activate && \ pip install \ west \ littlefs-python @@ -77,20 +65,31 @@ RUN mkdir -p /tmp/zephyrproject/ocre-runtime COPY west.yml /tmp/zephyrproject/ocre-runtime/west.yml -RUN . .venv/bin/activate && \ +RUN . /opt/zephyr-venv/bin/activate && \ cd /tmp/zephyrproject && \ west init -l ocre-runtime && \ west update -n zephyr && \ west packages pip --install && \ - west sdk install -t \ + west sdk install --install-base /opt -t \ x86_64-zephyr-elf \ aarch64-zephyr-elf \ arm-zephyr-eabi -FROM base AS ocre-dev +FROM base AS ocre-ci -COPY --from=zephyr-sdk /home/ocre-dev /home/ocre-dev +COPY --from=zephyr-sdk /opt/. /opt -RUN printf "\n%s\n" '. ~/.venv/bin/activate' >> /home/ocre-dev/.bashrc +RUN printf "\n%s\n" '. /opt/zephyr-venv/bin/activate' >> /etc/skel/.bashrc + +FROM ocre-ci AS ocre-dev + +# Accomodate the user for devcontainer +RUN (userdel -r $USERNAME ; userdel -r `id -nu $USER_UID` ; groupdel `id -ng $USER_GID`) || true \ + && groupadd --gid $USER_GID $USERNAME \ + && useradd --uid $USER_UID --gid $USER_GID -m $USERNAME -s /bin/bash \ + && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \ + && chmod 0440 /etc/sudoers.d/$USERNAME + +USER $USERNAME -WORKDIR /home/ocre-dev/zephyrproject +WORKDIR /home/$USERNAME diff --git a/.devcontainer/zephyr/devcontainer.json b/.devcontainer/zephyr/devcontainer.json index 791f9ec2..59b8818b 100644 --- a/.devcontainer/zephyr/devcontainer.json +++ b/.devcontainer/zephyr/devcontainer.json @@ -1,8 +1,14 @@ { "build": { "dockerfile": "Dockerfile", - "context": "../.." + "context": "../..", + "args": { + "USERNAME": "${localEnv:USER}", + "USER_UID": "${localEnv:REMOTE_UID:1000}", + "USER_GID": "${localEnv:REMOTE_GID:1000}" + } }, - "remoteUser": "ocre-dev", - "postCreateCommand": "sudo chown ocre-dev /workspaces" + "remoteUser": "${localEnv:USER}", + "postCreateCommand": "sudo chown ${localEnv:USER} .." + } diff --git a/.github/workflows/devcontainer-linux.yml b/.github/workflows/devcontainer-linux.yml index 2cac4af0..1e2d342b 100644 --- a/.github/workflows/devcontainer-linux.yml +++ b/.github/workflows/devcontainer-linux.yml @@ -63,8 +63,6 @@ jobs: with: context: .devcontainer/linux file: .devcontainer/linux/Dockerfile + target: ocre-ci push: true tags: ghcr.io/${{ github.repository }}/devcontainer-linux:${{ needs.necessary.outputs.devcontainer-tag }} - build-args: | - USER_UID=1001 - USER_GID=127 diff --git a/.github/workflows/devcontainer-zephyr.yml b/.github/workflows/devcontainer-zephyr.yml index 75af42cd..53a94b8a 100644 --- a/.github/workflows/devcontainer-zephyr.yml +++ b/.github/workflows/devcontainer-zephyr.yml @@ -65,8 +65,6 @@ jobs: with: context: . file: .devcontainer/zephyr/Dockerfile + target: ocre-ci push: true tags: ghcr.io/${{ github.repository }}/devcontainer-zephyr:${{ needs.necessary.outputs.devcontainer-tag }} - build-args: | - USER_UID=1001 - USER_GID=127 diff --git a/.github/workflows/formatting-checks.yml b/.github/workflows/formatting-checks.yml index 9fd74799..9f10451b 100644 --- a/.github/workflows/formatting-checks.yml +++ b/.github/workflows/formatting-checks.yml @@ -20,7 +20,6 @@ jobs: runs-on: self-hosted container: image: ghcr.io/${{ github.repository }}/devcontainer-linux:${{ inputs.devcontainer-tag }} - options: --user 1000:1000 steps: - name: checkout uses: actions/checkout@v5 diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 126ab9ce..e0230bf2 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -20,7 +20,6 @@ jobs: runs-on: self-hosted container: image: ghcr.io/${{ github.repository }}/devcontainer-linux:${{ inputs.devcontainer-tag }} - options: --user 1000:1000 steps: - name: Checkout uses: actions/checkout@v4 diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index 9d12b6fe..de53f3bd 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -20,7 +20,6 @@ jobs: runs-on: self-hosted container: image: ghcr.io/${{ github.repository }}/devcontainer-zephyr:${{ inputs.devcontainer-tag }} - options: --user 1000:1000 strategy: matrix: board: @@ -34,11 +33,9 @@ jobs: - name: Checkout uses: actions/checkout@v4 with: + path: ocre-runtime submodules: true - - name: Configure West SDK - run: cp -r /home/ocre-dev/.cmake ~ - - name: West init run: | . /home/ocre-dev/.venv/bin/activate From 22bba564300e885b24f0a786551f8447eedfbf04 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Fri, 26 Dec 2025 17:40:41 +0100 Subject: [PATCH 215/234] fix(ocre): remove spurious destruction of mutex This mutex is initialized statically. It should not be destroyed. Signed-off-by: Marco Casaroli --- src/ocre/ocre.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/ocre/ocre.c b/src/ocre/ocre.c index 5292003d..cfb553ee 100644 --- a/src/ocre/ocre.c +++ b/src/ocre/ocre.c @@ -450,11 +450,6 @@ void ocre_deinitialize(void) free(r_elt); } - - int rc = pthread_mutex_destroy(&contexts_mutex); - if (rc) { - LOG_ERR("Failed to destroy context mutex: rc=%d", rc); - } } int ocre_is_valid_id(const char *id) From bfdebed6ea49a0ee49451e04ec1fa51fe3c9e182 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Fri, 26 Dec 2025 17:41:30 +0100 Subject: [PATCH 216/234] feat(container): use semaphore for start signalling We switch from conditional variable to semaphore which is ligheter and have more compatible semantics for this case. Signed-off-by: Marco Casaroli --- src/ocre/container.c | 36 +++++++++++------------ src/runtime/include/ocre/runtime/vtable.h | 5 ++-- src/runtime/wamr/wamr.c | 11 +++---- 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/ocre/container.c b/src/ocre/container.c index d10eb625..554e3153 100644 --- a/src/ocre/container.c +++ b/src/ocre/container.c @@ -11,7 +11,7 @@ #include #include #include - +#include #include #include #include @@ -29,7 +29,7 @@ struct ocre_container { bool detached; ocre_container_status_t status; pthread_mutex_t mutex; - pthread_cond_t cond_start; + sem_t sem_start; pthread_cond_t cond_stop; void *runtime_context; pthread_t thread; @@ -41,9 +41,9 @@ struct ocre_container { }; struct container_thread_params { - int (*func)(void *, pthread_cond_t *); + int (*func)(void *, sem_t *); struct ocre_container *container; - pthread_cond_t *cond; + sem_t *sem; }; static void *container_thread(void *arg) @@ -54,7 +54,7 @@ static void *container_thread(void *arg) /* Run the container */ - int result = params->func(container->runtime_context, params->cond); + int result = params->func(container->runtime_context, params->sem); /* Exited */ @@ -239,9 +239,9 @@ struct ocre_container *ocre_container_create(const char *img_path, const char *w goto error_mutex; } - rc = pthread_cond_init(&container->cond_start, NULL); + rc = sem_init(&container->sem_start, 0, 0); if (rc) { - LOG_ERR("Failed to initialize start conditional variable: rc=%d", rc); + LOG_ERR("Failed to initialize start semaphore: rc=%d, errno=%d", rc, errno); goto error_mutex; } @@ -262,9 +262,9 @@ struct ocre_container *ocre_container_create(const char *img_path, const char *w return container; error_cond: - rc = pthread_cond_destroy(&container->cond_start); + rc = sem_destroy(&container->sem_start); if (rc) { - LOG_ERR("Failed to deinitialize start conditional variable: rc=%d", rc); + LOG_ERR("Failed to deinitialize start semaphore: rc=%d", rc); } rc = pthread_cond_destroy(&container->cond_stop); @@ -311,9 +311,9 @@ int ocre_container_destroy(struct ocre_container *container) LOG_ERR("Failed to deinitialize mutex: rc=%d", rc); } - rc = pthread_cond_destroy(&container->cond_start); + rc = sem_destroy(&container->sem_start); if (rc) { - LOG_ERR("Failed to deinitialize start conditional variable: rc=%d", rc); + LOG_ERR("Failed to deinitialize start semaphore: rc=%d", rc); } rc = pthread_cond_destroy(&container->cond_stop); @@ -370,7 +370,7 @@ int ocre_container_start(struct ocre_container *container) memset(params, 0, sizeof(struct container_thread_params)); params->container = container; params->func = container->runtime->thread_execute; - params->cond = &container->cond_start; + params->sem = &container->sem_start; container->status = OCRE_CONTAINER_STATUS_RUNNING; rc = pthread_create(&container->thread, &container->attr, container_thread, params); @@ -381,20 +381,20 @@ int ocre_container_start(struct ocre_container *container) LOG_INF("Waiting for container '%s' to start", container->id); - rc = pthread_cond_wait(&container->cond_start, &container->mutex); + rc = pthread_mutex_unlock(&container->mutex); if (rc) { - LOG_ERR("Failed to wait on start conditional variable: rc=%d", rc); + LOG_ERR("Failed to unlock mutex: rc=%d", rc); goto error_status; } - LOG_INF("Started container '%s' on runtime '%s'", container->id, container->runtime->runtime_name); - - rc = pthread_mutex_unlock(&container->mutex); + rc = sem_wait(&container->sem_start); if (rc) { - LOG_ERR("Failed to unlock mutex: rc=%d", rc); + LOG_ERR("Failed to wait on start semaphore: rc=%d", rc); goto error_status; } + LOG_INF("Started container '%s' on runtime '%s'", container->id, container->runtime->runtime_name); + if (!container->detached) { /* This will block until the container thread exits */ diff --git a/src/runtime/include/ocre/runtime/vtable.h b/src/runtime/include/ocre/runtime/vtable.h index 8f0b07ab..2410af81 100644 --- a/src/runtime/include/ocre/runtime/vtable.h +++ b/src/runtime/include/ocre/runtime/vtable.h @@ -10,6 +10,7 @@ #include #include +#include /** * @brief Runtime Engine Virtual Table @@ -95,13 +96,13 @@ struct ocre_runtime_vtable { * the container's main function, block and eventually return the exit code. * * @param runtime_context Pointer to the runtime context returned by create - * @param cond Pointer to the conditional variable to signal when the instance is ready to + * @param sem Pointer to the semaphore to post to when the instance is ready to * be killed * * @return status code of the execution: 0 on success, non-zero on failure */ - int (*thread_execute)(void *runtime_context, pthread_cond_t *cond); + int (*thread_execute)(void *runtime_context, sem_t *sem); /** * @brief Stop a runtime instance diff --git a/src/runtime/wamr/wamr.c b/src/runtime/wamr/wamr.c index fba3a25f..2ed0d46c 100644 --- a/src/runtime/wamr/wamr.c +++ b/src/runtime/wamr/wamr.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -48,7 +49,7 @@ struct wamr_context { size_t dir_map_list_len; }; -static int instance_execute(void *runtime_context, pthread_cond_t *cond) +static int instance_execute(void *runtime_context, sem_t *sem) { struct wamr_context *context = runtime_context; @@ -81,9 +82,9 @@ static int instance_execute(void *runtime_context, pthread_cond_t *cond) * exception. */ - int rc = pthread_cond_signal(cond); + int rc = sem_post(sem); if (rc) { - LOG_WRN("Failed to signal start conditional variable: rc=%d", rc); + LOG_WRN("Failed to signal start semaphore: rc=%d", rc); } /* Execute main function */ @@ -120,13 +121,13 @@ static int instance_execute(void *runtime_context, pthread_cond_t *cond) return exit_code; } -static int instance_thread_execute(void *arg, pthread_cond_t *cond) +static int instance_thread_execute(void *arg, sem_t *sem) { struct wamr_context *context = arg; wasm_runtime_init_thread_env(); - int ret = instance_execute(context, cond); + int ret = instance_execute(context, sem); wasm_runtime_destroy_thread_env(); From 59915dd8413bf4329e24427a60a57795150aec04 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 5 Jan 2026 11:34:23 +0100 Subject: [PATCH 217/234] ci(zephyr): use correct location for venv Now, the venv is installed in /opt/zephyr-venv Signed-off-by: Marco Casaroli --- .github/workflows/zephyr.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index de53f3bd..a47bc98a 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -38,17 +38,17 @@ jobs: - name: West init run: | - . /home/ocre-dev/.venv/bin/activate + . /opt/zephyr-venv/bin/activate west init -l . - name: West update run: | - . /home/ocre-dev/.venv/bin/activate + . /opt/zephyr-venv/bin/activate west update - name: West build run: | - . /home/ocre-dev/.venv/bin/activate + . /opt/zephyr-venv/bin/activate west build -p always -b ${{ matrix.board }} src/samples/${{ matrix.app }}/zephyr - name: Set sane board name From de528ecf523886134eb0892655e4c6e2c82c6d6d Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 5 Jan 2026 11:55:16 +0100 Subject: [PATCH 218/234] ci: pass user to container This option is required for docker to create files and directories owned by the same user as if we were not running workflows in docker. This is because if we run as a different user, the github runner will bind mount the directory and docker will create files as a different user (root) and these files cannot be deleted on self hosted runners. As a workaround, we just pass the user of our self-hosted runner so that the files will be created with the correct permissions in the container. Signed-off-by: Marco Casaroli --- .github/workflows/formatting-checks.yml | 1 + .github/workflows/linux.yml | 1 + .github/workflows/zephyr.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/.github/workflows/formatting-checks.yml b/.github/workflows/formatting-checks.yml index 9f10451b..9fd74799 100644 --- a/.github/workflows/formatting-checks.yml +++ b/.github/workflows/formatting-checks.yml @@ -20,6 +20,7 @@ jobs: runs-on: self-hosted container: image: ghcr.io/${{ github.repository }}/devcontainer-linux:${{ inputs.devcontainer-tag }} + options: --user 1000:1000 steps: - name: checkout uses: actions/checkout@v5 diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index e0230bf2..126ab9ce 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -20,6 +20,7 @@ jobs: runs-on: self-hosted container: image: ghcr.io/${{ github.repository }}/devcontainer-linux:${{ inputs.devcontainer-tag }} + options: --user 1000:1000 steps: - name: Checkout uses: actions/checkout@v4 diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index a47bc98a..81c8d9bd 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -20,6 +20,7 @@ jobs: runs-on: self-hosted container: image: ghcr.io/${{ github.repository }}/devcontainer-zephyr:${{ inputs.devcontainer-tag }} + options: --user 1000:1000 strategy: matrix: board: From 508c53b636c5390478ee36e4502d3a4c136aa9cd Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 6 Jan 2026 15:24:33 +0100 Subject: [PATCH 219/234] ci(zephyr): delete build directory before build On self-hosted runners, the workspace is not automatically cleaned up. In the Linux build, the build directory lays inside the source, which is cleaned up automatically by actions/checkout. However, in Zephyr, since the build directory is not inside the repository tree, we should do this explicitly. Signed-off-by: Marco Casaroli --- .github/workflows/zephyr.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index 81c8d9bd..28a6f571 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -47,6 +47,9 @@ jobs: . /opt/zephyr-venv/bin/activate west update + - name: Clean build directory + run: rm -rf build + - name: West build run: | . /opt/zephyr-venv/bin/activate From a8c87504a334d3f1622a46617ff6a53f472d2d43 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 6 Jan 2026 16:33:48 +0100 Subject: [PATCH 220/234] ci(zephyr): remove .west before init We also remove the .west directory so we can do west init. This is necessary for self hosted runners as they have the execution files from the old workspace. Signed-off-by: Marco Casaroli --- .github/workflows/zephyr.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index 28a6f571..a4561db0 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -37,6 +37,9 @@ jobs: path: ocre-runtime submodules: true + - name: Clean .west directory + run: rm -rf ../.west + - name: West init run: | . /opt/zephyr-venv/bin/activate From 33d54203c60ecbef0c05a19c4764c12cd474b8be Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 7 Jan 2026 11:29:55 +0100 Subject: [PATCH 221/234] chore: delete unused file Signed-off-by: Marco Casaroli --- src/ocre/ocre_input_file.h | 337 ------------------------------------- 1 file changed, 337 deletions(-) delete mode 100644 src/ocre/ocre_input_file.h diff --git a/src/ocre/ocre_input_file.h b/src/ocre/ocre_input_file.h deleted file mode 100644 index 74a39052..00000000 --- a/src/ocre/ocre_input_file.h +++ /dev/null @@ -1,337 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef OCRE_INPUT_FILE_H -#define OCRE_INPUT_FILE_H -// Sample WASM binary data -static unsigned char wasm_binary[] = { - 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x35, 0x09, 0x60, - 0x03, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x03, 0x7f, 0x7e, 0x7f, 0x01, - 0x7e, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, - 0x60, 0x04, 0x7f, 0x7e, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x04, 0x7f, 0x7f, - 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x00, 0x60, 0x00, 0x00, 0x60, - 0x00, 0x01, 0x7f, 0x02, 0xb0, 0x01, 0x05, 0x16, 0x77, 0x61, 0x73, 0x69, - 0x5f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, 0x72, - 0x65, 0x76, 0x69, 0x65, 0x77, 0x31, 0x08, 0x66, 0x64, 0x5f, 0x63, 0x6c, - 0x6f, 0x73, 0x65, 0x00, 0x02, 0x16, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x73, - 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x76, - 0x69, 0x65, 0x77, 0x31, 0x0d, 0x66, 0x64, 0x5f, 0x66, 0x64, 0x73, 0x74, - 0x61, 0x74, 0x5f, 0x67, 0x65, 0x74, 0x00, 0x03, 0x16, 0x77, 0x61, 0x73, - 0x69, 0x5f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, - 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x31, 0x07, 0x66, 0x64, 0x5f, 0x73, - 0x65, 0x65, 0x6b, 0x00, 0x04, 0x16, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x73, - 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x76, - 0x69, 0x65, 0x77, 0x31, 0x08, 0x66, 0x64, 0x5f, 0x77, 0x72, 0x69, 0x74, - 0x65, 0x00, 0x05, 0x16, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x73, 0x6e, 0x61, - 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, - 0x77, 0x31, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x5f, 0x65, 0x78, 0x69, 0x74, - 0x00, 0x06, 0x03, 0x1d, 0x1c, 0x07, 0x07, 0x08, 0x02, 0x03, 0x04, 0x05, - 0x06, 0x07, 0x07, 0x08, 0x07, 0x02, 0x05, 0x03, 0x03, 0x02, 0x07, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x01, 0x01, 0x00, 0x02, 0x04, 0x05, 0x01, - 0x70, 0x01, 0x05, 0x05, 0x05, 0x03, 0x01, 0x00, 0x02, 0x06, 0x0d, 0x02, - 0x7f, 0x01, 0x41, 0xc0, 0x91, 0x04, 0x0b, 0x7f, 0x00, 0x41, 0x00, 0x0b, - 0x07, 0x1a, 0x03, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, - 0x06, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 0x06, 0x04, 0x6d, 0x61, - 0x69, 0x6e, 0x00, 0x07, 0x09, 0x0a, 0x01, 0x00, 0x41, 0x01, 0x0b, 0x04, - 0x1a, 0x18, 0x1c, 0x1e, 0x0a, 0x93, 0x1a, 0x1c, 0x02, 0x00, 0x0b, 0x51, - 0x01, 0x01, 0x7f, 0x02, 0x40, 0x02, 0x40, 0x23, 0x81, 0x80, 0x80, 0x80, - 0x00, 0x41, 0xa0, 0x89, 0x80, 0x80, 0x00, 0x6a, 0x28, 0x02, 0x00, 0x0d, - 0x00, 0x23, 0x81, 0x80, 0x80, 0x80, 0x00, 0x41, 0xa0, 0x89, 0x80, 0x80, - 0x00, 0x6a, 0x41, 0x01, 0x36, 0x02, 0x00, 0x10, 0x85, 0x80, 0x80, 0x80, - 0x00, 0x10, 0x87, 0x80, 0x80, 0x80, 0x00, 0x21, 0x00, 0x10, 0x8e, 0x80, - 0x80, 0x80, 0x00, 0x20, 0x00, 0x0d, 0x01, 0x0f, 0x0b, 0x00, 0x0b, 0x20, - 0x00, 0x10, 0x8c, 0x80, 0x80, 0x80, 0x00, 0x00, 0x0b, 0x11, 0x00, 0x41, - 0x80, 0x88, 0x80, 0x80, 0x00, 0x10, 0x95, 0x80, 0x80, 0x80, 0x00, 0x1a, - 0x41, 0x00, 0x0b, 0x0f, 0x00, 0x20, 0x00, 0x10, 0x80, 0x80, 0x80, 0x80, - 0x00, 0x41, 0xff, 0xff, 0x03, 0x71, 0x0b, 0x11, 0x00, 0x20, 0x00, 0x20, - 0x01, 0x10, 0x81, 0x80, 0x80, 0x80, 0x00, 0x41, 0xff, 0xff, 0x03, 0x71, - 0x0b, 0x15, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x20, 0x03, 0x10, - 0x82, 0x80, 0x80, 0x80, 0x00, 0x41, 0xff, 0xff, 0x03, 0x71, 0x0b, 0x15, - 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x20, 0x03, 0x10, 0x83, 0x80, - 0x80, 0x80, 0x00, 0x41, 0xff, 0xff, 0x03, 0x71, 0x0b, 0x0b, 0x00, 0x20, - 0x00, 0x10, 0x84, 0x80, 0x80, 0x80, 0x00, 0x00, 0x0b, 0x02, 0x00, 0x0b, - 0x0e, 0x00, 0x10, 0x8d, 0x80, 0x80, 0x80, 0x00, 0x10, 0x90, 0x80, 0x80, - 0x80, 0x00, 0x0b, 0x08, 0x00, 0x41, 0xa4, 0x89, 0x80, 0x80, 0x00, 0x0b, - 0xa3, 0x03, 0x01, 0x03, 0x7f, 0x02, 0x40, 0x10, 0x8f, 0x80, 0x80, 0x80, - 0x00, 0x28, 0x02, 0x00, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x03, 0x40, 0x02, - 0x40, 0x20, 0x00, 0x28, 0x02, 0x14, 0x20, 0x00, 0x28, 0x02, 0x18, 0x46, - 0x0d, 0x00, 0x20, 0x00, 0x41, 0x00, 0x41, 0x00, 0x20, 0x00, 0x28, 0x02, - 0x20, 0x11, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, - 0x1a, 0x0b, 0x02, 0x40, 0x20, 0x00, 0x28, 0x02, 0x04, 0x22, 0x01, 0x20, - 0x00, 0x28, 0x02, 0x08, 0x22, 0x02, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x20, - 0x01, 0x20, 0x02, 0x6b, 0xac, 0x41, 0x01, 0x20, 0x00, 0x28, 0x02, 0x24, - 0x11, 0x81, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x1a, - 0x0b, 0x20, 0x00, 0x28, 0x02, 0x34, 0x22, 0x00, 0x0d, 0x00, 0x0b, 0x0b, - 0x02, 0x40, 0x41, 0x00, 0x28, 0x02, 0xa8, 0x89, 0x80, 0x80, 0x00, 0x22, - 0x00, 0x45, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x00, 0x28, 0x02, 0x14, 0x20, - 0x00, 0x28, 0x02, 0x18, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x41, 0x00, 0x41, - 0x00, 0x20, 0x00, 0x28, 0x02, 0x20, 0x11, 0x80, 0x80, 0x80, 0x80, 0x00, - 0x80, 0x80, 0x80, 0x80, 0x00, 0x1a, 0x0b, 0x20, 0x00, 0x28, 0x02, 0x04, - 0x22, 0x01, 0x20, 0x00, 0x28, 0x02, 0x08, 0x22, 0x02, 0x46, 0x0d, 0x00, - 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x6b, 0xac, 0x41, 0x01, 0x20, 0x00, - 0x28, 0x02, 0x24, 0x11, 0x81, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, - 0x80, 0x00, 0x1a, 0x0b, 0x02, 0x40, 0x41, 0x00, 0x28, 0x02, 0x90, 0x89, - 0x80, 0x80, 0x00, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x00, - 0x28, 0x02, 0x14, 0x20, 0x00, 0x28, 0x02, 0x18, 0x46, 0x0d, 0x00, 0x20, - 0x00, 0x41, 0x00, 0x41, 0x00, 0x20, 0x00, 0x28, 0x02, 0x20, 0x11, 0x80, - 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x1a, 0x0b, 0x20, - 0x00, 0x28, 0x02, 0x04, 0x22, 0x01, 0x20, 0x00, 0x28, 0x02, 0x08, 0x22, - 0x02, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x6b, 0xac, - 0x41, 0x01, 0x20, 0x00, 0x28, 0x02, 0x24, 0x11, 0x81, 0x80, 0x80, 0x80, - 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x1a, 0x0b, 0x02, 0x40, 0x41, 0x00, - 0x28, 0x02, 0xa8, 0x89, 0x80, 0x80, 0x00, 0x22, 0x00, 0x45, 0x0d, 0x00, - 0x02, 0x40, 0x20, 0x00, 0x28, 0x02, 0x14, 0x20, 0x00, 0x28, 0x02, 0x18, - 0x46, 0x0d, 0x00, 0x20, 0x00, 0x41, 0x00, 0x41, 0x00, 0x20, 0x00, 0x28, - 0x02, 0x20, 0x11, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, - 0x00, 0x1a, 0x0b, 0x20, 0x00, 0x28, 0x02, 0x04, 0x22, 0x01, 0x20, 0x00, - 0x28, 0x02, 0x08, 0x22, 0x02, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x20, 0x01, - 0x20, 0x02, 0x6b, 0xac, 0x41, 0x01, 0x20, 0x00, 0x28, 0x02, 0x24, 0x11, - 0x81, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x1a, 0x0b, - 0x0b, 0x5c, 0x01, 0x01, 0x7f, 0x20, 0x00, 0x20, 0x00, 0x28, 0x02, 0x3c, - 0x22, 0x01, 0x41, 0x7f, 0x6a, 0x20, 0x01, 0x72, 0x36, 0x02, 0x3c, 0x02, - 0x40, 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x01, 0x41, 0x08, 0x71, 0x45, - 0x0d, 0x00, 0x20, 0x00, 0x20, 0x01, 0x41, 0x20, 0x72, 0x36, 0x02, 0x00, - 0x41, 0x7f, 0x0f, 0x0b, 0x20, 0x00, 0x42, 0x00, 0x37, 0x02, 0x04, 0x20, - 0x00, 0x20, 0x00, 0x28, 0x02, 0x28, 0x22, 0x01, 0x36, 0x02, 0x18, 0x20, - 0x00, 0x20, 0x01, 0x36, 0x02, 0x14, 0x20, 0x00, 0x20, 0x01, 0x20, 0x00, - 0x28, 0x02, 0x2c, 0x6a, 0x36, 0x02, 0x10, 0x41, 0x00, 0x0b, 0xa8, 0x02, - 0x01, 0x05, 0x7f, 0x20, 0x02, 0x20, 0x01, 0x6c, 0x21, 0x04, 0x02, 0x40, - 0x02, 0x40, 0x20, 0x03, 0x28, 0x02, 0x10, 0x22, 0x05, 0x0d, 0x00, 0x41, - 0x00, 0x21, 0x06, 0x20, 0x03, 0x10, 0x91, 0x80, 0x80, 0x80, 0x00, 0x0d, - 0x01, 0x20, 0x03, 0x28, 0x02, 0x10, 0x21, 0x05, 0x0b, 0x02, 0x40, 0x20, - 0x05, 0x20, 0x03, 0x28, 0x02, 0x14, 0x22, 0x07, 0x6b, 0x20, 0x04, 0x4f, - 0x0d, 0x00, 0x20, 0x03, 0x20, 0x00, 0x20, 0x04, 0x20, 0x03, 0x28, 0x02, - 0x20, 0x11, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, - 0x21, 0x06, 0x0c, 0x01, 0x0b, 0x41, 0x00, 0x21, 0x08, 0x02, 0x40, 0x02, - 0x40, 0x20, 0x04, 0x0d, 0x00, 0x20, 0x04, 0x21, 0x05, 0x0c, 0x01, 0x0b, - 0x41, 0x00, 0x21, 0x05, 0x02, 0x40, 0x20, 0x03, 0x28, 0x02, 0x40, 0x41, - 0x00, 0x4e, 0x0d, 0x00, 0x20, 0x04, 0x21, 0x05, 0x0c, 0x01, 0x0b, 0x20, - 0x00, 0x20, 0x04, 0x6a, 0x21, 0x06, 0x02, 0x40, 0x03, 0x40, 0x20, 0x06, - 0x20, 0x05, 0x6a, 0x41, 0x7f, 0x6a, 0x2d, 0x00, 0x00, 0x41, 0x0a, 0x46, - 0x0d, 0x01, 0x20, 0x04, 0x20, 0x05, 0x41, 0x7f, 0x6a, 0x22, 0x05, 0x6a, - 0x0d, 0x00, 0x0b, 0x41, 0x00, 0x21, 0x08, 0x20, 0x04, 0x21, 0x05, 0x0c, - 0x01, 0x0b, 0x20, 0x03, 0x20, 0x00, 0x20, 0x04, 0x20, 0x05, 0x6a, 0x22, - 0x08, 0x20, 0x03, 0x28, 0x02, 0x20, 0x11, 0x80, 0x80, 0x80, 0x80, 0x00, - 0x80, 0x80, 0x80, 0x80, 0x00, 0x22, 0x06, 0x20, 0x08, 0x49, 0x0d, 0x01, - 0x20, 0x08, 0x20, 0x00, 0x6a, 0x21, 0x00, 0x41, 0x00, 0x20, 0x05, 0x6b, - 0x21, 0x05, 0x20, 0x03, 0x28, 0x02, 0x14, 0x21, 0x07, 0x0b, 0x20, 0x07, - 0x20, 0x00, 0x20, 0x05, 0x10, 0x9f, 0x80, 0x80, 0x80, 0x00, 0x1a, 0x20, - 0x03, 0x20, 0x03, 0x28, 0x02, 0x14, 0x20, 0x05, 0x6a, 0x36, 0x02, 0x14, - 0x20, 0x08, 0x20, 0x05, 0x6a, 0x21, 0x06, 0x0b, 0x02, 0x40, 0x20, 0x06, - 0x20, 0x04, 0x47, 0x0d, 0x00, 0x20, 0x02, 0x41, 0x00, 0x20, 0x01, 0x1b, - 0x0f, 0x0b, 0x20, 0x06, 0x20, 0x01, 0x6e, 0x0b, 0x24, 0x01, 0x01, 0x7f, - 0x20, 0x00, 0x10, 0xa0, 0x80, 0x80, 0x80, 0x00, 0x21, 0x02, 0x41, 0x7f, - 0x41, 0x00, 0x20, 0x02, 0x20, 0x00, 0x41, 0x01, 0x20, 0x02, 0x20, 0x01, - 0x10, 0x92, 0x80, 0x80, 0x80, 0x00, 0x47, 0x1b, 0x0b, 0xb3, 0x01, 0x01, - 0x03, 0x7f, 0x23, 0x80, 0x80, 0x80, 0x80, 0x00, 0x41, 0x10, 0x6b, 0x22, - 0x02, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, 0x02, 0x20, 0x01, 0x3a, - 0x00, 0x0f, 0x02, 0x40, 0x02, 0x40, 0x20, 0x00, 0x28, 0x02, 0x10, 0x22, - 0x03, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x00, 0x10, 0x91, 0x80, 0x80, 0x80, - 0x00, 0x45, 0x0d, 0x00, 0x41, 0x7f, 0x21, 0x03, 0x0c, 0x02, 0x0b, 0x20, - 0x00, 0x28, 0x02, 0x10, 0x21, 0x03, 0x0b, 0x02, 0x40, 0x20, 0x00, 0x28, - 0x02, 0x14, 0x22, 0x04, 0x20, 0x03, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x28, - 0x02, 0x40, 0x20, 0x01, 0x41, 0xff, 0x01, 0x71, 0x22, 0x03, 0x46, 0x0d, - 0x00, 0x20, 0x00, 0x20, 0x04, 0x41, 0x01, 0x6a, 0x36, 0x02, 0x14, 0x20, - 0x04, 0x20, 0x01, 0x3a, 0x00, 0x00, 0x0c, 0x01, 0x0b, 0x02, 0x40, 0x20, - 0x00, 0x20, 0x02, 0x41, 0x0f, 0x6a, 0x41, 0x01, 0x20, 0x00, 0x28, 0x02, - 0x20, 0x11, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, - 0x41, 0x01, 0x46, 0x0d, 0x00, 0x41, 0x7f, 0x21, 0x03, 0x0c, 0x01, 0x0b, - 0x20, 0x02, 0x2d, 0x00, 0x0f, 0x21, 0x03, 0x0b, 0x20, 0x02, 0x41, 0x10, - 0x6a, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, 0x03, 0x0b, 0x6c, 0x00, - 0x02, 0x40, 0x20, 0x00, 0x41, 0xa0, 0x88, 0x80, 0x80, 0x00, 0x10, 0x93, - 0x80, 0x80, 0x80, 0x00, 0x41, 0x00, 0x4e, 0x0d, 0x00, 0x41, 0x7f, 0x0f, - 0x0b, 0x02, 0x40, 0x41, 0x00, 0x28, 0x02, 0xe0, 0x88, 0x80, 0x80, 0x00, - 0x41, 0x0a, 0x46, 0x0d, 0x00, 0x41, 0x00, 0x28, 0x02, 0xb4, 0x88, 0x80, - 0x80, 0x00, 0x22, 0x00, 0x41, 0x00, 0x28, 0x02, 0xb0, 0x88, 0x80, 0x80, - 0x00, 0x46, 0x0d, 0x00, 0x41, 0x00, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x36, - 0x02, 0xb4, 0x88, 0x80, 0x80, 0x00, 0x20, 0x00, 0x41, 0x0a, 0x3a, 0x00, - 0x00, 0x41, 0x00, 0x0f, 0x0b, 0x41, 0xa0, 0x88, 0x80, 0x80, 0x00, 0x41, - 0x0a, 0x10, 0x94, 0x80, 0x80, 0x80, 0x00, 0x41, 0x1f, 0x75, 0x0b, 0x02, - 0x00, 0x0b, 0x27, 0x00, 0x10, 0x96, 0x80, 0x80, 0x80, 0x00, 0x02, 0x40, - 0x20, 0x00, 0x10, 0x88, 0x80, 0x80, 0x80, 0x00, 0x22, 0x00, 0x0d, 0x00, - 0x41, 0x00, 0x0f, 0x0b, 0x41, 0x00, 0x20, 0x00, 0x36, 0x02, 0xac, 0x89, - 0x80, 0x80, 0x00, 0x41, 0x7f, 0x0b, 0x0d, 0x00, 0x20, 0x00, 0x28, 0x02, - 0x38, 0x10, 0x97, 0x80, 0x80, 0x80, 0x00, 0x0b, 0x71, 0x01, 0x02, 0x7f, - 0x23, 0x80, 0x80, 0x80, 0x80, 0x00, 0x41, 0x10, 0x6b, 0x22, 0x03, 0x24, - 0x80, 0x80, 0x80, 0x80, 0x00, 0x41, 0x7f, 0x21, 0x04, 0x02, 0x40, 0x02, - 0x40, 0x20, 0x02, 0x41, 0x7f, 0x4a, 0x0d, 0x00, 0x41, 0x00, 0x41, 0x1c, - 0x36, 0x02, 0xac, 0x89, 0x80, 0x80, 0x00, 0x0c, 0x01, 0x0b, 0x02, 0x40, - 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x20, 0x03, 0x41, 0x0c, 0x6a, 0x10, - 0x8b, 0x80, 0x80, 0x80, 0x00, 0x22, 0x02, 0x45, 0x0d, 0x00, 0x41, 0x00, - 0x20, 0x02, 0x36, 0x02, 0xac, 0x89, 0x80, 0x80, 0x00, 0x41, 0x7f, 0x21, - 0x04, 0x0c, 0x01, 0x0b, 0x20, 0x03, 0x28, 0x02, 0x0c, 0x21, 0x04, 0x0b, - 0x20, 0x03, 0x41, 0x10, 0x6a, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, - 0x04, 0x0b, 0xbb, 0x02, 0x01, 0x07, 0x7f, 0x23, 0x80, 0x80, 0x80, 0x80, - 0x00, 0x41, 0x10, 0x6b, 0x22, 0x03, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, - 0x20, 0x03, 0x20, 0x02, 0x36, 0x02, 0x0c, 0x20, 0x03, 0x20, 0x01, 0x36, - 0x02, 0x08, 0x20, 0x03, 0x20, 0x00, 0x28, 0x02, 0x18, 0x22, 0x01, 0x36, - 0x02, 0x00, 0x20, 0x03, 0x20, 0x00, 0x28, 0x02, 0x14, 0x20, 0x01, 0x6b, - 0x22, 0x04, 0x36, 0x02, 0x04, 0x41, 0x02, 0x21, 0x05, 0x02, 0x40, 0x02, - 0x40, 0x20, 0x00, 0x28, 0x02, 0x38, 0x20, 0x03, 0x41, 0x02, 0x10, 0x99, - 0x80, 0x80, 0x80, 0x00, 0x22, 0x01, 0x20, 0x04, 0x20, 0x02, 0x6a, 0x22, - 0x06, 0x46, 0x0d, 0x00, 0x20, 0x03, 0x21, 0x04, 0x03, 0x40, 0x02, 0x40, - 0x20, 0x01, 0x41, 0x7f, 0x4a, 0x0d, 0x00, 0x41, 0x00, 0x21, 0x01, 0x20, - 0x00, 0x41, 0x00, 0x36, 0x02, 0x18, 0x20, 0x00, 0x42, 0x00, 0x37, 0x03, - 0x10, 0x20, 0x00, 0x20, 0x00, 0x28, 0x02, 0x00, 0x41, 0x20, 0x72, 0x36, - 0x02, 0x00, 0x20, 0x05, 0x41, 0x02, 0x46, 0x0d, 0x03, 0x20, 0x02, 0x20, - 0x04, 0x28, 0x02, 0x04, 0x6b, 0x21, 0x01, 0x0c, 0x03, 0x0b, 0x20, 0x04, - 0x20, 0x01, 0x20, 0x04, 0x28, 0x02, 0x04, 0x22, 0x07, 0x4b, 0x22, 0x08, - 0x41, 0x03, 0x74, 0x6a, 0x22, 0x09, 0x20, 0x09, 0x28, 0x02, 0x00, 0x20, - 0x01, 0x20, 0x07, 0x41, 0x00, 0x20, 0x08, 0x1b, 0x6b, 0x22, 0x07, 0x6a, - 0x36, 0x02, 0x00, 0x20, 0x04, 0x41, 0x0c, 0x41, 0x04, 0x20, 0x08, 0x1b, - 0x6a, 0x22, 0x04, 0x20, 0x04, 0x28, 0x02, 0x00, 0x20, 0x07, 0x6b, 0x36, - 0x02, 0x00, 0x20, 0x09, 0x21, 0x04, 0x20, 0x06, 0x20, 0x01, 0x6b, 0x22, - 0x06, 0x20, 0x00, 0x28, 0x02, 0x38, 0x20, 0x09, 0x20, 0x05, 0x20, 0x08, - 0x6b, 0x22, 0x05, 0x10, 0x99, 0x80, 0x80, 0x80, 0x00, 0x22, 0x01, 0x47, - 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x00, 0x20, 0x00, 0x28, 0x02, 0x28, 0x22, - 0x01, 0x36, 0x02, 0x18, 0x20, 0x00, 0x20, 0x01, 0x36, 0x02, 0x14, 0x20, - 0x00, 0x20, 0x01, 0x20, 0x00, 0x28, 0x02, 0x2c, 0x6a, 0x36, 0x02, 0x10, - 0x20, 0x02, 0x21, 0x01, 0x0b, 0x20, 0x03, 0x41, 0x10, 0x6a, 0x24, 0x80, - 0x80, 0x80, 0x80, 0x00, 0x20, 0x01, 0x0b, 0x66, 0x01, 0x02, 0x7f, 0x23, - 0x80, 0x80, 0x80, 0x80, 0x00, 0x41, 0x20, 0x6b, 0x22, 0x01, 0x24, 0x80, - 0x80, 0x80, 0x80, 0x00, 0x02, 0x40, 0x02, 0x40, 0x20, 0x00, 0x20, 0x01, - 0x41, 0x08, 0x6a, 0x10, 0x89, 0x80, 0x80, 0x80, 0x00, 0x22, 0x00, 0x0d, - 0x00, 0x41, 0x3b, 0x21, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x08, 0x41, 0x02, - 0x47, 0x0d, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x10, 0x41, 0x24, 0x71, 0x0d, - 0x00, 0x41, 0x01, 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x41, 0x00, 0x21, 0x02, - 0x41, 0x00, 0x20, 0x00, 0x36, 0x02, 0xac, 0x89, 0x80, 0x80, 0x00, 0x0b, - 0x20, 0x01, 0x41, 0x20, 0x6a, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, - 0x02, 0x0b, 0x3b, 0x00, 0x20, 0x00, 0x41, 0x81, 0x80, 0x80, 0x80, 0x00, - 0x36, 0x02, 0x20, 0x02, 0x40, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x41, 0xc0, - 0x00, 0x71, 0x0d, 0x00, 0x20, 0x00, 0x28, 0x02, 0x38, 0x10, 0x9b, 0x80, - 0x80, 0x80, 0x00, 0x0d, 0x00, 0x20, 0x00, 0x41, 0x7f, 0x36, 0x02, 0x40, - 0x0b, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x10, 0x9a, 0x80, 0x80, 0x80, - 0x00, 0x0b, 0x64, 0x01, 0x01, 0x7f, 0x23, 0x80, 0x80, 0x80, 0x80, 0x00, - 0x41, 0x10, 0x6b, 0x22, 0x03, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, 0x02, - 0x40, 0x02, 0x40, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x41, 0xff, 0x01, - 0x71, 0x20, 0x03, 0x41, 0x08, 0x6a, 0x10, 0x8a, 0x80, 0x80, 0x80, 0x00, - 0x22, 0x02, 0x45, 0x0d, 0x00, 0x41, 0x00, 0x41, 0xc6, 0x00, 0x20, 0x02, - 0x20, 0x02, 0x41, 0xcc, 0x00, 0x46, 0x1b, 0x36, 0x02, 0xac, 0x89, 0x80, - 0x80, 0x00, 0x42, 0x7f, 0x21, 0x01, 0x0c, 0x01, 0x0b, 0x20, 0x03, 0x29, - 0x03, 0x08, 0x21, 0x01, 0x0b, 0x20, 0x03, 0x41, 0x10, 0x6a, 0x24, 0x80, - 0x80, 0x80, 0x80, 0x00, 0x20, 0x01, 0x0b, 0x11, 0x00, 0x20, 0x00, 0x28, - 0x02, 0x38, 0x20, 0x01, 0x20, 0x02, 0x10, 0x9d, 0x80, 0x80, 0x80, 0x00, - 0x0b, 0xee, 0x07, 0x01, 0x04, 0x7f, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, - 0x20, 0x02, 0x41, 0x20, 0x4b, 0x0d, 0x00, 0x20, 0x01, 0x41, 0x03, 0x71, - 0x45, 0x0d, 0x01, 0x20, 0x02, 0x45, 0x0d, 0x01, 0x20, 0x00, 0x20, 0x01, - 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x02, 0x41, 0x7f, 0x6a, 0x21, - 0x03, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x21, 0x04, 0x20, 0x01, 0x41, 0x01, - 0x6a, 0x22, 0x05, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x02, 0x20, 0x03, 0x45, - 0x0d, 0x02, 0x20, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x01, 0x3a, 0x00, 0x01, - 0x20, 0x02, 0x41, 0x7e, 0x6a, 0x21, 0x03, 0x20, 0x00, 0x41, 0x02, 0x6a, - 0x21, 0x04, 0x20, 0x01, 0x41, 0x02, 0x6a, 0x22, 0x05, 0x41, 0x03, 0x71, - 0x45, 0x0d, 0x02, 0x20, 0x03, 0x45, 0x0d, 0x02, 0x20, 0x00, 0x20, 0x01, - 0x2d, 0x00, 0x02, 0x3a, 0x00, 0x02, 0x20, 0x02, 0x41, 0x7d, 0x6a, 0x21, - 0x03, 0x20, 0x00, 0x41, 0x03, 0x6a, 0x21, 0x04, 0x20, 0x01, 0x41, 0x03, - 0x6a, 0x22, 0x05, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x02, 0x20, 0x03, 0x45, - 0x0d, 0x02, 0x20, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x03, 0x3a, 0x00, 0x03, - 0x20, 0x02, 0x41, 0x7c, 0x6a, 0x21, 0x03, 0x20, 0x00, 0x41, 0x04, 0x6a, - 0x21, 0x04, 0x20, 0x01, 0x41, 0x04, 0x6a, 0x21, 0x05, 0x0c, 0x02, 0x0b, - 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0xfc, 0x0a, 0x00, 0x00, 0x20, 0x00, - 0x0f, 0x0b, 0x20, 0x02, 0x21, 0x03, 0x20, 0x00, 0x21, 0x04, 0x20, 0x01, - 0x21, 0x05, 0x0b, 0x02, 0x40, 0x02, 0x40, 0x20, 0x04, 0x41, 0x03, 0x71, - 0x22, 0x02, 0x0d, 0x00, 0x02, 0x40, 0x02, 0x40, 0x20, 0x03, 0x41, 0x10, - 0x4f, 0x0d, 0x00, 0x20, 0x03, 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x02, 0x40, - 0x20, 0x03, 0x41, 0x70, 0x6a, 0x22, 0x02, 0x41, 0x10, 0x71, 0x0d, 0x00, - 0x20, 0x04, 0x20, 0x05, 0x29, 0x02, 0x00, 0x37, 0x02, 0x00, 0x20, 0x04, - 0x20, 0x05, 0x29, 0x02, 0x08, 0x37, 0x02, 0x08, 0x20, 0x04, 0x41, 0x10, - 0x6a, 0x21, 0x04, 0x20, 0x05, 0x41, 0x10, 0x6a, 0x21, 0x05, 0x20, 0x02, - 0x21, 0x03, 0x0b, 0x20, 0x02, 0x41, 0x10, 0x49, 0x0d, 0x00, 0x20, 0x03, - 0x21, 0x02, 0x03, 0x40, 0x20, 0x04, 0x20, 0x05, 0x29, 0x02, 0x00, 0x37, - 0x02, 0x00, 0x20, 0x04, 0x20, 0x05, 0x29, 0x02, 0x08, 0x37, 0x02, 0x08, - 0x20, 0x04, 0x20, 0x05, 0x29, 0x02, 0x10, 0x37, 0x02, 0x10, 0x20, 0x04, - 0x20, 0x05, 0x29, 0x02, 0x18, 0x37, 0x02, 0x18, 0x20, 0x04, 0x41, 0x20, - 0x6a, 0x21, 0x04, 0x20, 0x05, 0x41, 0x20, 0x6a, 0x21, 0x05, 0x20, 0x02, - 0x41, 0x60, 0x6a, 0x22, 0x02, 0x41, 0x0f, 0x4b, 0x0d, 0x00, 0x0b, 0x0b, - 0x02, 0x40, 0x20, 0x02, 0x41, 0x08, 0x49, 0x0d, 0x00, 0x20, 0x04, 0x20, - 0x05, 0x29, 0x02, 0x00, 0x37, 0x02, 0x00, 0x20, 0x05, 0x41, 0x08, 0x6a, - 0x21, 0x05, 0x20, 0x04, 0x41, 0x08, 0x6a, 0x21, 0x04, 0x0b, 0x02, 0x40, - 0x20, 0x02, 0x41, 0x04, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x04, 0x20, 0x05, - 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, 0x20, 0x05, 0x41, 0x04, 0x6a, 0x21, - 0x05, 0x20, 0x04, 0x41, 0x04, 0x6a, 0x21, 0x04, 0x0b, 0x02, 0x40, 0x20, - 0x02, 0x41, 0x02, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x04, 0x20, 0x05, 0x2f, - 0x00, 0x00, 0x3b, 0x00, 0x00, 0x20, 0x04, 0x41, 0x02, 0x6a, 0x21, 0x04, - 0x20, 0x05, 0x41, 0x02, 0x6a, 0x21, 0x05, 0x0b, 0x20, 0x02, 0x41, 0x01, - 0x71, 0x45, 0x0d, 0x01, 0x20, 0x04, 0x20, 0x05, 0x2d, 0x00, 0x00, 0x3a, - 0x00, 0x00, 0x20, 0x00, 0x0f, 0x0b, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, - 0x02, 0x40, 0x02, 0x40, 0x20, 0x03, 0x41, 0x20, 0x49, 0x0d, 0x00, 0x20, - 0x04, 0x20, 0x05, 0x28, 0x02, 0x00, 0x22, 0x03, 0x3a, 0x00, 0x00, 0x02, - 0x40, 0x02, 0x40, 0x20, 0x02, 0x41, 0x7f, 0x6a, 0x0e, 0x03, 0x03, 0x00, - 0x01, 0x03, 0x0b, 0x20, 0x04, 0x20, 0x03, 0x41, 0x08, 0x76, 0x3a, 0x00, - 0x01, 0x20, 0x04, 0x20, 0x05, 0x41, 0x06, 0x6a, 0x29, 0x01, 0x00, 0x37, - 0x02, 0x06, 0x20, 0x04, 0x20, 0x05, 0x28, 0x02, 0x04, 0x41, 0x10, 0x74, - 0x20, 0x03, 0x41, 0x10, 0x76, 0x72, 0x36, 0x02, 0x02, 0x20, 0x04, 0x41, - 0x12, 0x6a, 0x21, 0x02, 0x20, 0x05, 0x41, 0x12, 0x6a, 0x21, 0x01, 0x41, - 0x0e, 0x21, 0x06, 0x20, 0x05, 0x41, 0x0e, 0x6a, 0x28, 0x01, 0x00, 0x21, - 0x05, 0x41, 0x0e, 0x21, 0x03, 0x0c, 0x03, 0x0b, 0x20, 0x04, 0x20, 0x05, - 0x41, 0x05, 0x6a, 0x29, 0x00, 0x00, 0x37, 0x02, 0x05, 0x20, 0x04, 0x20, - 0x05, 0x28, 0x02, 0x04, 0x41, 0x18, 0x74, 0x20, 0x03, 0x41, 0x08, 0x76, - 0x72, 0x36, 0x02, 0x01, 0x20, 0x04, 0x41, 0x11, 0x6a, 0x21, 0x02, 0x20, - 0x05, 0x41, 0x11, 0x6a, 0x21, 0x01, 0x41, 0x0d, 0x21, 0x06, 0x20, 0x05, - 0x41, 0x0d, 0x6a, 0x28, 0x00, 0x00, 0x21, 0x05, 0x41, 0x0f, 0x21, 0x03, - 0x0c, 0x02, 0x0b, 0x02, 0x40, 0x02, 0x40, 0x20, 0x03, 0x41, 0x10, 0x4f, - 0x0d, 0x00, 0x20, 0x04, 0x21, 0x02, 0x20, 0x05, 0x21, 0x01, 0x0c, 0x01, - 0x0b, 0x20, 0x04, 0x20, 0x05, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x20, - 0x04, 0x20, 0x05, 0x28, 0x00, 0x01, 0x36, 0x00, 0x01, 0x20, 0x04, 0x20, - 0x05, 0x29, 0x00, 0x05, 0x37, 0x00, 0x05, 0x20, 0x04, 0x20, 0x05, 0x2f, - 0x00, 0x0d, 0x3b, 0x00, 0x0d, 0x20, 0x04, 0x20, 0x05, 0x2d, 0x00, 0x0f, - 0x3a, 0x00, 0x0f, 0x20, 0x04, 0x41, 0x10, 0x6a, 0x21, 0x02, 0x20, 0x05, - 0x41, 0x10, 0x6a, 0x21, 0x01, 0x0b, 0x20, 0x03, 0x41, 0x08, 0x71, 0x0d, - 0x02, 0x0c, 0x03, 0x0b, 0x20, 0x04, 0x20, 0x03, 0x41, 0x10, 0x76, 0x3a, - 0x00, 0x02, 0x20, 0x04, 0x20, 0x03, 0x41, 0x08, 0x76, 0x3a, 0x00, 0x01, - 0x20, 0x04, 0x20, 0x05, 0x41, 0x07, 0x6a, 0x29, 0x00, 0x00, 0x37, 0x02, - 0x07, 0x20, 0x04, 0x20, 0x05, 0x28, 0x02, 0x04, 0x41, 0x08, 0x74, 0x20, - 0x03, 0x41, 0x18, 0x76, 0x72, 0x36, 0x02, 0x03, 0x20, 0x04, 0x41, 0x13, - 0x6a, 0x21, 0x02, 0x20, 0x05, 0x41, 0x13, 0x6a, 0x21, 0x01, 0x41, 0x0f, - 0x21, 0x06, 0x20, 0x05, 0x41, 0x0f, 0x6a, 0x28, 0x00, 0x00, 0x21, 0x05, - 0x41, 0x0d, 0x21, 0x03, 0x0b, 0x20, 0x04, 0x20, 0x06, 0x6a, 0x20, 0x05, - 0x36, 0x02, 0x00, 0x0b, 0x20, 0x02, 0x20, 0x01, 0x29, 0x00, 0x00, 0x37, - 0x00, 0x00, 0x20, 0x02, 0x41, 0x08, 0x6a, 0x21, 0x02, 0x20, 0x01, 0x41, - 0x08, 0x6a, 0x21, 0x01, 0x0b, 0x02, 0x40, 0x20, 0x03, 0x41, 0x04, 0x71, - 0x45, 0x0d, 0x00, 0x20, 0x02, 0x20, 0x01, 0x28, 0x00, 0x00, 0x36, 0x00, - 0x00, 0x20, 0x02, 0x41, 0x04, 0x6a, 0x21, 0x02, 0x20, 0x01, 0x41, 0x04, - 0x6a, 0x21, 0x01, 0x0b, 0x02, 0x40, 0x20, 0x03, 0x41, 0x02, 0x71, 0x45, - 0x0d, 0x00, 0x20, 0x02, 0x20, 0x01, 0x2f, 0x00, 0x00, 0x3b, 0x00, 0x00, - 0x20, 0x02, 0x41, 0x02, 0x6a, 0x21, 0x02, 0x20, 0x01, 0x41, 0x02, 0x6a, - 0x21, 0x01, 0x0b, 0x20, 0x03, 0x41, 0x01, 0x71, 0x45, 0x0d, 0x00, 0x20, - 0x02, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x0b, 0x20, 0x00, - 0x0b, 0xcf, 0x01, 0x01, 0x03, 0x7f, 0x20, 0x00, 0x21, 0x01, 0x02, 0x40, - 0x02, 0x40, 0x20, 0x00, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x00, 0x02, 0x40, - 0x20, 0x00, 0x2d, 0x00, 0x00, 0x0d, 0x00, 0x20, 0x00, 0x20, 0x00, 0x6b, - 0x0f, 0x0b, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x22, 0x01, 0x41, 0x03, 0x71, - 0x45, 0x0d, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x45, 0x0d, 0x01, 0x20, - 0x00, 0x41, 0x02, 0x6a, 0x22, 0x01, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x00, - 0x20, 0x01, 0x2d, 0x00, 0x00, 0x45, 0x0d, 0x01, 0x20, 0x00, 0x41, 0x03, - 0x6a, 0x22, 0x01, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x01, 0x2d, - 0x00, 0x00, 0x45, 0x0d, 0x01, 0x20, 0x00, 0x41, 0x04, 0x6a, 0x22, 0x01, - 0x41, 0x03, 0x71, 0x0d, 0x01, 0x0b, 0x20, 0x01, 0x41, 0x7c, 0x6a, 0x21, - 0x02, 0x20, 0x01, 0x41, 0x7b, 0x6a, 0x21, 0x01, 0x03, 0x40, 0x20, 0x01, - 0x41, 0x04, 0x6a, 0x21, 0x01, 0x41, 0x80, 0x82, 0x84, 0x08, 0x20, 0x02, - 0x41, 0x04, 0x6a, 0x22, 0x02, 0x28, 0x02, 0x00, 0x22, 0x03, 0x6b, 0x20, - 0x03, 0x72, 0x41, 0x80, 0x81, 0x82, 0x84, 0x78, 0x71, 0x41, 0x80, 0x81, - 0x82, 0x84, 0x78, 0x46, 0x0d, 0x00, 0x0b, 0x03, 0x40, 0x20, 0x01, 0x41, - 0x01, 0x6a, 0x21, 0x01, 0x20, 0x02, 0x2d, 0x00, 0x00, 0x21, 0x03, 0x20, - 0x02, 0x41, 0x01, 0x6a, 0x21, 0x02, 0x20, 0x03, 0x0d, 0x00, 0x0b, 0x0b, - 0x20, 0x01, 0x20, 0x00, 0x6b, 0x0b, 0x0b, 0x9d, 0x01, 0x02, 0x00, 0x41, - 0x80, 0x08, 0x0b, 0x1c, 0x0a, 0x0a, 0x09, 0x48, 0x65, 0x6c, 0x6c, 0x6f, - 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, - 0x4f, 0x63, 0x72, 0x65, 0x21, 0x0a, 0x0a, 0x00, 0x00, 0x41, 0xa0, 0x08, - 0x0b, 0x74, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xb8, 0x04, 0x00, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00 - }; - -static unsigned int wasm_binary_len = 3850; - -#endif // OCRE_INPUT_FILE_H From 2f5d1d470e7ec48e6af834090bfd3bb8cbe2f9ea Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 7 Jan 2026 11:38:32 +0100 Subject: [PATCH 222/234] chore: delete unused file Signed-off-by: Marco Casaroli --- src/samples-mini/zephyr/main.c | 114 --------------------------------- 1 file changed, 114 deletions(-) delete mode 100644 src/samples-mini/zephyr/main.c diff --git a/src/samples-mini/zephyr/main.c b/src/samples-mini/zephyr/main.c deleted file mode 100644 index 049bb203..00000000 --- a/src/samples-mini/zephyr/main.c +++ /dev/null @@ -1,114 +0,0 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include "ocre_core_external.h" -#include -#include - -#include -#include - -#ifdef HAS_GENERATED_INPUT -#include -#else -#include -#endif - -void create_sample_container(); -int ocre_network_init(); - -int main(int argc, char *argv[]) { - ocre_cs_ctx ctx; - ocre_container_init_arguments_t args; -#ifdef OCRE_INPUT_FILE_NAME - const char *container_filename = OCRE_INPUT_FILE_NAME; -#else - const char *container_filename = "hello-from-ocre"; -#endif - -#ifdef CONFIG_OCRE_NETWORKING - int net_status = ocre_network_init(); - if (net_status < 0) { - printf("Unable to connect to network\n"); - } else { - printf("Network is UP\n"); - } -#endif - - ocre_app_storage_init(); - - // Step 1: Initialize the Ocre runtime - ocre_container_runtime_status_t ret = ocre_container_runtime_init(&ctx, &args); - - if (ret == RUNTIME_STATUS_INITIALIZED) { - printf("\n\nOcre runtime started\n"); - - create_sample_container(container_filename); - - // Step 2: Create the container, this allocates and loads the container binary - ocre_container_data_t ocre_container_data; - int container_ID; - - ocre_container_data.heap_size = 0; - snprintf(ocre_container_data.name, sizeof(ocre_container_data.name), "%s", container_filename); - snprintf(ocre_container_data.sha256, sizeof(ocre_container_data.sha256), "%s", container_filename); - ocre_container_data.timers = 0; - ocre_container_runtime_create_container(&ctx, &ocre_container_data, &container_ID, NULL); - - // Step 3: Execute the container - ocre_container_runtime_run_container(container_ID, NULL); - // Loop forever, without this the application will exit and stop all execution - while (true) { - core_sleep_ms(1000); - } - - } else { - printf("\n\nOcre runtime failed to start.\n"); - } -} - -/** - * Creates a container image file using the sample "hello-word" WASM module - * This is for demostration purposes only and does not perform any error checking. - * - * @param file_name a string containing the name of the file to create - */ - -void create_sample_container(char *file_name) { - static char file_path[64]; - struct fs_file_t f; - snprintf((char *)&file_path, 64, "/lfs/ocre/images/%s.bin", file_name); - int res; - - fs_file_t_init(&f); - res = fs_open(&f, file_path, FS_O_CREATE | FS_O_RDWR); - - fs_write(&f, &wasm_binary, wasm_binary_len); - fs_close(&f); -} - -int ocre_network_init() { - - struct net_if *iface = net_if_get_default(); - net_dhcpv4_start(iface); - - printf("Waiting for network to be ready...\n"); - - int sleep_cnt = 0; - while (!net_if_is_up(iface) && (sleep_cnt < 10)) { - k_sleep(K_MSEC(200)); - sleep_cnt++; - } - - if (!net_if_is_up(iface)) { - return -ENOTCONN; - } - - return 0; -} From f544c62e76fbdc2031abe5e0fd6e7bc48b577f37 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 7 Jan 2026 11:57:26 +0100 Subject: [PATCH 223/234] chore: add license banners Signed-off-by: Marco Casaroli --- .devcontainer/linux/Dockerfile | 5 +++++ .devcontainer/zephyr/Dockerfile | 5 +++++ ocre-sdk | 2 +- scripts/c_array.awk | 1 - src/platform/include/ocre/platform/file.h | 7 +++++++ src/platform/include/ocre/platform/memory.h | 7 +++++++ src/platform/posix/CMakeLists.txt | 5 +++++ src/platform/posix/file_alloc_fread.c | 7 +++++++ src/platform/posix/file_alloc_read.c | 7 +++++++ src/platform/posix/file_mmap.c | 7 +++++++ src/platform/posix/include/ocre/platform/config.h | 7 +++++++ src/platform/posix/include/ocre/platform/log.h | 7 +++++++ src/platform/posix/log.c | 7 +++++++ src/platform/posix/memory.c | 7 +++++++ src/platform/zephyr/CMakeLists.txt | 5 +++++ src/platform/zephyr/include/ocre/platform/config.h | 7 +++++++ src/platform/zephyr/include/ocre/platform/log.h | 7 +++++++ src/samples/demo/zephyr/boards/native_sim_64.overlay | 7 +++++++ .../demo/zephyr/boards/pico_plus2_rp2350b_m33.overlay | 7 +++++++ .../demo/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay | 7 +++++++ src/samples/demo/zephyr/fstab.overlay | 7 +++++++ src/samples/mini/zephyr/boards/native_sim_64.overlay | 7 +++++++ .../mini/zephyr/boards/pico_plus2_rp2350b_m33.overlay | 7 +++++++ .../mini/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay | 7 +++++++ src/samples/mini/zephyr/fstab.overlay | 9 ++++++++- 25 files changed, 155 insertions(+), 3 deletions(-) diff --git a/.devcontainer/linux/Dockerfile b/.devcontainer/linux/Dockerfile index fe17ccf4..268c3f37 100644 --- a/.devcontainer/linux/Dockerfile +++ b/.devcontainer/linux/Dockerfile @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + FROM ubuntu:24.04 AS ocre-ci ARG USERNAME=ocre-dev diff --git a/.devcontainer/zephyr/Dockerfile b/.devcontainer/zephyr/Dockerfile index f3a695e4..57c48bb7 100644 --- a/.devcontainer/zephyr/Dockerfile +++ b/.devcontainer/zephyr/Dockerfile @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + FROM ubuntu:24.04 AS base ARG USERNAME=ocre-dev diff --git a/ocre-sdk b/ocre-sdk index 6f53f2ff..2030fa2b 160000 --- a/ocre-sdk +++ b/ocre-sdk @@ -1 +1 @@ -Subproject commit 6f53f2ffa46f61413846514fdf9a4ebeaa715518 +Subproject commit 2030fa2b079f04e596384f24bdc5bc782a7f8b01 diff --git a/scripts/c_array.awk b/scripts/c_array.awk index 5b444c71..a1e14cb4 100644 --- a/scripts/c_array.awk +++ b/scripts/c_array.awk @@ -1,4 +1,3 @@ -#!/bin/bash # @copyright Copyright (c) contributors to Project Ocre, # which has been established as Project Ocre a Series of LF Projects, LLC # diff --git a/src/platform/include/ocre/platform/file.h b/src/platform/include/ocre/platform/file.h index 42f250d7..e124b038 100644 --- a/src/platform/include/ocre/platform/file.h +++ b/src/platform/include/ocre/platform/file.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include void *ocre_load_file(const char *path, size_t *size); diff --git a/src/platform/include/ocre/platform/memory.h b/src/platform/include/ocre/platform/memory.h index 0202d4f9..15ba7df2 100644 --- a/src/platform/include/ocre/platform/memory.h +++ b/src/platform/include/ocre/platform/memory.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include void *user_malloc(size_t size); diff --git a/src/platform/posix/CMakeLists.txt b/src/platform/posix/CMakeLists.txt index 012e220c..e0f19383 100644 --- a/src/platform/posix/CMakeLists.txt +++ b/src/platform/posix/CMakeLists.txt @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + add_library(OcrePlatform) target_sources(OcrePlatform diff --git a/src/platform/posix/file_alloc_fread.c b/src/platform/posix/file_alloc_fread.c index 599ae068..83fcc9b7 100644 --- a/src/platform/posix/file_alloc_fread.c +++ b/src/platform/posix/file_alloc_fread.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include #include diff --git a/src/platform/posix/file_alloc_read.c b/src/platform/posix/file_alloc_read.c index f14c5bc2..64a0700a 100644 --- a/src/platform/posix/file_alloc_read.c +++ b/src/platform/posix/file_alloc_read.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include #include diff --git a/src/platform/posix/file_mmap.c b/src/platform/posix/file_mmap.c index 3ff927c8..58f253f7 100644 --- a/src/platform/posix/file_mmap.c +++ b/src/platform/posix/file_mmap.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include #include diff --git a/src/platform/posix/include/ocre/platform/config.h b/src/platform/posix/include/ocre/platform/config.h index 4035179f..2d6cd6c7 100644 --- a/src/platform/posix/include/ocre/platform/config.h +++ b/src/platform/posix/include/ocre/platform/config.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #ifndef OCRE_PLATFORM_POSIX_H #define OCRE_PLATFORM_POSIX_H diff --git a/src/platform/posix/include/ocre/platform/log.h b/src/platform/posix/include/ocre/platform/log.h index e0a3f16d..8b838c81 100644 --- a/src/platform/posix/include/ocre/platform/log.h +++ b/src/platform/posix/include/ocre/platform/log.h @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include "config.h" diff --git a/src/platform/posix/log.c b/src/platform/posix/log.c index ef0a97e5..997346d9 100644 --- a/src/platform/posix/log.c +++ b/src/platform/posix/log.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include int __ocre_log_level = CONFIG_OCRE_LOG_LEVEL_DEFAULT; diff --git a/src/platform/posix/memory.c b/src/platform/posix/memory.c index 6135fb7d..35e60838 100644 --- a/src/platform/posix/memory.c +++ b/src/platform/posix/memory.c @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include #include diff --git a/src/platform/zephyr/CMakeLists.txt b/src/platform/zephyr/CMakeLists.txt index 1ebf1ac0..90243df3 100644 --- a/src/platform/zephyr/CMakeLists.txt +++ b/src/platform/zephyr/CMakeLists.txt @@ -1,3 +1,8 @@ +# @copyright Copyright (c) contributors to Project Ocre, +# which has been established as Project Ocre a Series of LF Projects, LLC +# +# SPDX-License-Identifier: Apache-2.0 + add_library(OcrePlatform) target_sources(OcrePlatform diff --git a/src/platform/zephyr/include/ocre/platform/config.h b/src/platform/zephyr/include/ocre/platform/config.h index 7c18adf5..c3036fb8 100644 --- a/src/platform/zephyr/include/ocre/platform/config.h +++ b/src/platform/zephyr/include/ocre/platform/config.h @@ -1 +1,8 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + /* Zephyr includes autoconf.h automatically */ diff --git a/src/platform/zephyr/include/ocre/platform/log.h b/src/platform/zephyr/include/ocre/platform/log.h index 3cd34de3..b5b52021 100644 --- a/src/platform/zephyr/include/ocre/platform/log.h +++ b/src/platform/zephyr/include/ocre/platform/log.h @@ -1 +1,8 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include diff --git a/src/samples/demo/zephyr/boards/native_sim_64.overlay b/src/samples/demo/zephyr/boards/native_sim_64.overlay index eb2c157d..848942a0 100644 --- a/src/samples/demo/zephyr/boards/native_sim_64.overlay +++ b/src/samples/demo/zephyr/boards/native_sim_64.overlay @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + &flash0 { reg = < 0x0 DT_SIZE_M(32) >; }; diff --git a/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33.overlay b/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33.overlay index 24e3edbb..425ed0d8 100644 --- a/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33.overlay +++ b/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33.overlay @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + &flash0 { partitions { compatible = "fixed-partitions"; diff --git a/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay b/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay index 24e3edbb..425ed0d8 100644 --- a/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay +++ b/src/samples/demo/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + &flash0 { partitions { compatible = "fixed-partitions"; diff --git a/src/samples/demo/zephyr/fstab.overlay b/src/samples/demo/zephyr/fstab.overlay index a986be8d..811beedd 100644 --- a/src/samples/demo/zephyr/fstab.overlay +++ b/src/samples/demo/zephyr/fstab.overlay @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + / { fstab { compatible = "zephyr,fstab"; diff --git a/src/samples/mini/zephyr/boards/native_sim_64.overlay b/src/samples/mini/zephyr/boards/native_sim_64.overlay index eb2c157d..848942a0 100644 --- a/src/samples/mini/zephyr/boards/native_sim_64.overlay +++ b/src/samples/mini/zephyr/boards/native_sim_64.overlay @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + &flash0 { reg = < 0x0 DT_SIZE_M(32) >; }; diff --git a/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33.overlay b/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33.overlay index 24e3edbb..425ed0d8 100644 --- a/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33.overlay +++ b/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33.overlay @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + &flash0 { partitions { compatible = "fixed-partitions"; diff --git a/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay b/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay index 24e3edbb..425ed0d8 100644 --- a/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay +++ b/src/samples/mini/zephyr/boards/pico_plus2_rp2350b_m33_w.overlay @@ -1,3 +1,10 @@ +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + &flash0 { partitions { compatible = "fixed-partitions"; diff --git a/src/samples/mini/zephyr/fstab.overlay b/src/samples/mini/zephyr/fstab.overlay index a986be8d..fe261aac 100644 --- a/src/samples/mini/zephyr/fstab.overlay +++ b/src/samples/mini/zephyr/fstab.overlay @@ -1,4 +1,11 @@ -/ { +/** + * @copyright Copyright (c) contributors to Project Ocre, + * which has been established as Project Ocre a Series of LF Projects, LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + + / { fstab { compatible = "zephyr,fstab"; lfs1: lfs1 { From 611616c3b3f5946a21b9f6008c722c17ad87136c Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 7 Jan 2026 11:58:05 +0100 Subject: [PATCH 224/234] chore: remove workspace file Signed-off-by: Marco Casaroli --- ocre.code-workspace | 164 -------------------------------------------- 1 file changed, 164 deletions(-) delete mode 100644 ocre.code-workspace diff --git a/ocre.code-workspace b/ocre.code-workspace deleted file mode 100644 index 2a13006e..00000000 --- a/ocre.code-workspace +++ /dev/null @@ -1,164 +0,0 @@ -{ - "folders": [ - { - "path": ".." - } - ], - "settings": { - // Hush CMake - "cmake.configureOnOpen": false, - // CppTools and IntelliSense - "C_Cpp.workspaceParsingPriority": "medium", - "C_Cpp.default.cStandard": "c11", - "C_Cpp.default.browse.path": [ - "${workspaceFolder}/application/src" - ], - "C_Cpp.intelliSenseEngine": "default", - "C_Cpp.default.includePath": [ - "${workspaceFolder}/application/src/ocre", - "${workspaceFolder}/zephyr/include/" - ], - "C_Cpp.default.forcedInclude": [ - "${workspaceFolder}/build/zephyr/include/generated/autoconf.h" - ], - "C_Cpp.default.compileCommands": "${workspaceFolder}/build/compile_commands.json", - // Files - "files.exclude": { - "**/.git": true, - "**/.svn": true, - "**/.hg": true, - "**/CVS": true, - "**/.DS_Store": true, - "**/Thumbs.db": true - }, - // Kconfig - "kconfig.root": "${workspaceFolder}/application/Kconfig", - "files.associations": { - "net_private.h": "c", - "socket.h": "c", - "tls_internal.h": "c", - "sockets_internal.h": "c", - "iwasm_sm.h": "c", - "*.h": "c", - "*.c": "c", - "*.g": "c", - "*.tcc": "c", - "system_error": "c", - "array": "c", - "functional": "c", - "tuple": "c", - "type_traits": "c", - "utility": "c", - "__hash_table": "c", - "__split_buffer": "c", - "bitset": "c", - "deque": "c", - "initializer_list": "c", - "queue": "c", - "stack": "c", - "string": "c", - "string_view": "c", - "unordered_map": "c", - "vector": "c", - "__config": "c", - "__node_handle": "c" - }, - "editor.formatOnType": true, - }, - "tasks": { - "version": "2.0.0", - "tasks": [ - { - "label": "West Build", - "type": "shell", - "group": { - "kind": "build", - "isDefault": true - }, - "command": "west", - "args": [ - "build", - "--pristine", - "-b", - "${input:board}", - "${workspaceFolder}/application", - "-d", - "${workspaceFolder}/build", - "--", - "-DMODULE_EXT_ROOT=\"${workspaceFolder}/application\"", - ], - "problemMatcher": [ - "$gcc" - ], - } - ], - "inputs": [ - { - "id": "board", - "type": "pickString", - "options": [ - "native_sim", - "nucleo_h723zg", - "b_u585i_iot02a", - ], - "default": "native_sim", - "description": "See https://docs.zephyrproject.org/latest/boards/index.html" - } - ] - }, - "extensions": { - "recommendations": [ - "ms-vscode.cpptools-extension-pack", - "ms-python.python", - "ms-vscode.vscode-embedded-tools", - "ms-vscode.vscode-serial-monitor", - "marus25.cortex-debug", - ] - }, - "launch": { - "version": "0.2.0", - "configurations": [ - { - "name": "Cortex Debug - ST-LINK", - "cwd": "${workspaceFolder}", - "executable": "${workspaceFolder}/build/zephyr/zephyr.elf", - "request": "launch", - "type": "cortex-debug", - "runToEntryPoint": "main", - "servertype": "stlink", - "device": "STM32H7xx", // Changed for NUCLEO-H723ZG - "interface": "swd", - "showDevDebugOutput": "none", - "v1": false, - "stm32cubeprogrammer": "" - }, - { - "name": "(gdb) Launch", - "type": "cppdbg", - "request": "launch", - "program": "${workspaceFolder}/build/zephyr/zephyr.exe", - "args": [ - "-seed=$RANDOM", - "--flash=${workspaceFolder}/flash.bin" - ], - "stopAtEntry": false, - "cwd": "${fileDirname}", - "environment": [], - "externalConsole": false, - "MIMode": "gdb", - "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - }, - { - "description": "Set Disassembly Flavor to Intel", - "text": "-gdb-set disassembly-flavor intel", - "ignoreFailures": true - } - ] - } - ] - } -} From 8c14191ec345c8c3ae7dd17f8a4b7d14880061ef Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 7 Jan 2026 12:22:29 +0100 Subject: [PATCH 225/234] chore: remove spurious file Signed-off-by: Marco Casaroli --- .devcontainer/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .devcontainer/.DS_Store diff --git a/.devcontainer/.DS_Store b/.devcontainer/.DS_Store deleted file mode 100644 index 1ba0d2bfd4b44cee8a12dfed1e049be296b77620..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKJ5Iwu5SiApg@!9|0t&9co1IaJ zokVm9!HhKf*7I4f-&!6I5%G929T5$QD1i$04l!&I@r!Oq&n)8PxW=-$9p%?mS#QL; z;de41XSYuU&FPL7)H%PwN84LgSvD!E39QN6{P{g!zMOU=rr$)=v-LM5Ae{#ENHhNU2^1wutpET3 From f7606345e887b68d6ac3a30336ab4f30b9bf3fe0 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 7 Jan 2026 12:24:00 +0100 Subject: [PATCH 226/234] chore(gitignore): add .DS_Store Signed-off-by: Marco Casaroli --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 96de9c5a..d2232379 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,8 @@ settings.json src/ocre/commit_id.h +**/.DS_Store + # hidden files .* !.git From ec08a35c1dd2d8d47b529286c19f18307aad5fc4 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 7 Jan 2026 13:05:48 +0100 Subject: [PATCH 227/234] ci: use build server Signed-off-by: Marco Casaroli --- .github/workflows/devcontainer-linux.yml | 4 ++-- .github/workflows/devcontainer-zephyr.yml | 4 ++-- .github/workflows/formatting-checks.yml | 2 +- .github/workflows/linux.yml | 2 +- .github/workflows/zephyr.yml | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/devcontainer-linux.yml b/.github/workflows/devcontainer-linux.yml index 1e2d342b..59b0825e 100644 --- a/.github/workflows/devcontainer-linux.yml +++ b/.github/workflows/devcontainer-linux.yml @@ -14,7 +14,7 @@ on: jobs: necessary: name: Necessary? - runs-on: self-hosted + runs-on: ["self-hosted", "build-server"] outputs: build: ${{ steps.changed-files.outputs.all_changed_and_modified_files != '' }} devcontainer-tag: ${{ steps.devcontainer-tag.outputs.tag }} @@ -42,7 +42,7 @@ jobs: if: ${{ needs.necessary.outputs.build == 'true' }} needs: - necessary - runs-on: self-hosted + runs-on: ["self-hosted", "build-server"] steps: - name: Checkout the code diff --git a/.github/workflows/devcontainer-zephyr.yml b/.github/workflows/devcontainer-zephyr.yml index 53a94b8a..913fcedb 100644 --- a/.github/workflows/devcontainer-zephyr.yml +++ b/.github/workflows/devcontainer-zephyr.yml @@ -14,7 +14,7 @@ on: jobs: necessary: name: Necessary? - runs-on: self-hosted + runs-on: ["self-hosted", "build-server"] outputs: build: ${{ steps.changed-files.outputs.all_changed_and_modified_files != '' }} devcontainer-tag: ${{ steps.devcontainer-tag.outputs.tag }} @@ -44,7 +44,7 @@ jobs: if: ${{ needs.necessary.outputs.build == 'true' }} needs: - necessary - runs-on: self-hosted + runs-on: ["self-hosted", "build-server"] steps: - name: Checkout the code diff --git a/.github/workflows/formatting-checks.yml b/.github/workflows/formatting-checks.yml index 9fd74799..0023e545 100644 --- a/.github/workflows/formatting-checks.yml +++ b/.github/workflows/formatting-checks.yml @@ -17,7 +17,7 @@ on: jobs: format-checks: name: Formatting checks - runs-on: self-hosted + runs-on: ["self-hosted", "build-server"] container: image: ghcr.io/${{ github.repository }}/devcontainer-linux:${{ inputs.devcontainer-tag }} options: --user 1000:1000 diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 126ab9ce..404d6f3d 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -17,7 +17,7 @@ on: jobs: build-linux: name: Linux build - runs-on: self-hosted + runs-on: ["self-hosted", "build-server"] container: image: ghcr.io/${{ github.repository }}/devcontainer-linux:${{ inputs.devcontainer-tag }} options: --user 1000:1000 diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index a4561db0..2de39c37 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -17,7 +17,7 @@ on: jobs: build-zephyr: name: Zephyr build - runs-on: self-hosted + runs-on: ["self-hosted", "build-server"] container: image: ghcr.io/${{ github.repository }}/devcontainer-zephyr:${{ inputs.devcontainer-tag }} options: --user 1000:1000 From b0063e317e5529c33dc7c6a47d5e109154429b20 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Wed, 7 Jan 2026 14:53:05 +0100 Subject: [PATCH 228/234] chore: fix format Signed-off-by: Marco Casaroli --- src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.c b/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.c index 4a7c9cb4..f3e9de61 100644 --- a/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.c +++ b/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.c @@ -420,7 +420,7 @@ static void gpio_callback_handler(const struct device *port, struct gpio_callbac } //======================================================================================================================================================================================================================================================================================================== -// By Name +// By Name //======================================================================================================================================================================================================================================================================================================== static int find_port_index(const struct device *port) { From cd12c6afeea8a55caf945ae5e7cec436ac8819de Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 8 Jan 2026 09:55:45 +0100 Subject: [PATCH 229/234] chore: remove build.sh This script is broken because the new build system is different. The new build system is simple enough, so I believe this script might not be necessary anymore, however if we find it is necessary, we can re-create (and simplify) it. Signed-off-by: Marco Casaroli --- build.sh | 143 ------------------------------------------------------- 1 file changed, 143 deletions(-) delete mode 100755 build.sh diff --git a/build.sh b/build.sh deleted file mode 100755 index ac1da7b8..00000000 --- a/build.sh +++ /dev/null @@ -1,143 +0,0 @@ -#!/bin/bash - -# Function to display help -show_help() { - echo "Usage: $0 -t [-r] [-f [file2 ...]]" - echo " -t (Required) Specify the target. z for Zephyr and l for Linux" - echo " -r (Optional) Specify whether run after the build" - echo " -f (Optional) Specify one or more input files" - echo " -b (Optional, Zephyr only) Select board:" - echo " uw -> b_u585i_iot02a + W5500" - echo " ue -> b_u585i_iot02a + ENC28J60" - echo " note: when no board is selected, native_sim is the default target for Zephyr" - echo " -h Display help" - exit 0 -} - -RUN_MODE=false # Default: Run mode disabled -INPUT_FILES=() -BOARD_ARG="native_sim" - -# resolve absolute paths (portable, no readlink -f) -abs_path() { - local p="$1" - if [[ "$p" = /* ]]; then - echo "$p" - else - echo "$(cd "$(dirname "$p")" && pwd)/$(basename "$p")" - fi -} - -# Parse arguments -while [[ $# -gt 0 ]]; do - case "$1" in - -t) - if [[ -z "$2" || "$2" =~ ^- ]]; then - echo "Error: -t requires a value (z or l)" >&2 - exit 1 - fi - TARGET="$2" - shift 2 - ;; - -r) - RUN_MODE=true - shift - ;; - -f) - shift - while [[ $# -gt 0 && ! "$1" =~ ^- ]]; do - INPUT_FILES+=("$1") - shift - done - ;; - -b) - if [[ -z "$2" || "$2" =~ ^- ]]; then - echo "Error: -b requires a board argument" >&2 - exit 1 - fi - BOARD_ARG="$2" - shift 2 - ;; - -h) - show_help - ;; - *) - echo "Invalid option: $1" >&2 - show_help - ;; - esac -done - -# Normalize input files to absolute paths BEFORE any 'cd' -if [[ ${#INPUT_FILES[@]} -gt 0 ]]; then - for i in "${!INPUT_FILES[@]}"; do - INPUT_FILES[$i]="$(abs_path "${INPUT_FILES[$i]}")" - done -fi - -# Check if required argument is provided -if [[ "$TARGET" == "z" ]]; then - echo "Target is: Zephyr" - cd .. - case "$BOARD_ARG" in - uw) - ZEPHYR_BOARD="b_u585i_iot02a" - CONF_EXTRA="" - echo "Building for b_u585i_iot02a with W5500 support" - ;; - ue) - ZEPHYR_BOARD="b_u585i_iot02a" - CONF_EXTRA="-DCONF_FILE=prj.conf\;boards/${ZEPHYR_BOARD}.conf\;boards/enc28j60.conf \ - -DDTC_OVERLAY_FILE=boards/${ZEPHYR_BOARD}.overlay\;boards/enc28j60.overlay" - echo "Building for b_u585i_iot02a with ENC28J60 support" - ;; - *) - ZEPHYR_BOARD="$BOARD_ARG" - CONF_EXTRA="" - echo "Building for board: $ZEPHYR_BOARD" - ;; - esac - - if [[ ${#INPUT_FILES[@]} -gt 0 ]]; then - echo "Input files provided: ${INPUT_FILES[*]}" - rm flash.bin - west build -p -b $ZEPHYR_BOARD ./application -d build -- \ - -DMODULE_EXT_ROOT=`pwd`/application -DOCRE_INPUT_FILE="${INPUT_FILES[0]}" -DTARGET_PLATFORM_NAME=Zephyr $CONF_EXTRA || exit 1 - else - rm flash.bin - west build -p -b $ZEPHYR_BOARD ./application -d build -- \ - -DMODULE_EXT_ROOT=`pwd`/application -DTARGET_PLATFORM_NAME=Zephyr $CONF_EXTRA || exit 1 - fi -elif [[ "$TARGET" == "l" ]]; then - echo "Target is: Linux" - if [[ ! -d "build" ]]; then - echo "build folder does not exist. Creating: build" - mkdir -p "build" - fi - cd build - cmake .. -DTARGET_PLATFORM_NAME=Linux -DWAMR_DISABLE_STACK_HW_BOUND_CHECK=1 - # Capture make output to a file - make | tee build.log - BUILD_SUCCESS=false - if [[ $(tail -n 1 build.log) == "[100%] Built target app" ]]; then - BUILD_SUCCESS=true - fi - if [ "$BUILD_SUCCESS" == false ]; then - exit 1 - fi -else - echo "Target does not contain 'z' or 'l': exit" - exit 1 -fi - -# Execute run mode if -r flag is set and build was successful -if [[ "$TARGET" == "z" && "$RUN_MODE" = true ]]; then - west flash -elif [[ "$TARGET" == "l" && "$RUN_MODE" = true && "$BUILD_SUCCESS" = true ]]; then - if [[ ${#INPUT_FILES[@]} -gt 0 ]]; then - echo "Input files provided: ${INPUT_FILES[*]}" - ./app "${INPUT_FILES[@]}" - else - ./app - fi -fi From 860c94b7f64ecbd47a83f3007c31c8889e221bce Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 8 Jan 2026 10:14:36 +0100 Subject: [PATCH 230/234] chore: remove spurious file Signed-off-by: Marco Casaroli --- .clangd | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 .clangd diff --git a/.clangd b/.clangd deleted file mode 100644 index 7721f26c..00000000 --- a/.clangd +++ /dev/null @@ -1,2 +0,0 @@ -CompileFlags: - CompilationDatabase: build From a1c5ffe1bc0f8cb51337edf71f288f462bb44d76 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 8 Jan 2026 13:16:06 +0100 Subject: [PATCH 231/234] chore(ocre_api): remove obsolete file Signed-off-by: Marco Casaroli --- .../wamr/ocre_api/ocre_sensors/usage.md | 236 ------------------ 1 file changed, 236 deletions(-) delete mode 100644 src/runtime/wamr/ocre_api/ocre_sensors/usage.md diff --git a/src/runtime/wamr/ocre_api/ocre_sensors/usage.md b/src/runtime/wamr/ocre_api/ocre_sensors/usage.md deleted file mode 100644 index 2e907064..00000000 --- a/src/runtime/wamr/ocre_api/ocre_sensors/usage.md +++ /dev/null @@ -1,236 +0,0 @@ -1. Initializing the Sensor Environment - -``` -ocre_sensors_status_t status; - -status = ocre_sensors_init(); - -if (status != SENSOR_API_STATUS_INITIALIZED) { - -// Handle initialization error - -} -``` - -2. Discovering Sensors - -``` -ocre_sensor_t sensors[MAX_SENSORS]; - -status = ocre_sensors_discover_sensors(sensors); - -if (status != SENSOR_API_STATUS_INITIALIZED) { - -// Handle discovery error - -} -``` - -3. Opening a Sensor Channel - -``` -ocre_sensor_handle_t sensor_handle; - -status = ocre_sensors_open_channel(&sensor_handle); - -if (status != 0) { - -// Handle channel open error - -} -``` - -4. Reading Sensor Data - -``` -ocre_sensors_sample_t sample = sensor_read_sample(&sensor_handle); -``` - - - -5. Accessing Specific Sensor Channels - -``` -sensor_channel_t temperature = sensor_get_channel(sample, SENSOR_CHANNEL_TEMPERATURE); -``` - -6. Setting a Sensor Trigger - -``` -int subscription_id; - -status = ocre_sensors_set_trigger(sensor_handle, SENSOR_CHANNEL_TEMPERATURE, DATA_READY, my_callback, &subscription_id); - -if (status != 0) { - -// Handle trigger set error - -} -``` - -7. Clearing a Sensor Trigger - -``` -status = ocre_sensors_clear_trigger(sensor_handle, SENSOR_CHANNEL_TEMPERATURE, subscription_id); - -if (status != 0) { - -// Handle trigger clear error - -}``` - -8. Cleaning Up the Sensor Environment - -```status = ocre_sensors_cleanup(); - -if (status != 0) { - -// Handle cleanup error - -} -``` - -Usage - -``` - -#include - -#include - -#include "ocre_sensors.h" - - - -// Define the callback function to handle trigger events - -void my_callback(ocre_sensor_handle_t sensor_handle, sensor_channel_t channel, const ocre_sensor_value *data, void *ptr) { - -printf("Trigger event on sensor %d, channel %d\n", sensor_handle.id, channel); - -printf("Sensor data: Integer = %d, Floating = %d\n", data->integer, data->floating); - -} - - - -// Main function demonstrating the use of the Ocre Sensors API - -void main(void) { - - ocre_sensors_status_t status; - - ocre_sensor_t sensors[MAX_SENSORS]; // Array to hold discovered sensors - - ocre_sensor_handle_t sensor_handle; // Handle for the sensor to be used - - int subscription_id; // ID for the trigger subscription - - - -// Step 1: Initialize the sensors environment - - status = ocre_sensors_init(); - - if (status != SENSOR_API_STATUS_INITIALIZED) { - - printf("Failed to initialize sensors. Status: %d\n", status); - - return; - - } - - - -// Step 2: Discover available sensors - - status = ocre_sensors_discover_sensors(sensors); - - if (status != SENSOR_API_STATUS_INITIALIZED) { - - printf("Failed to discover sensors. Status: %d\n", status); - - return; - - } - - - -// Step 3: Open a channel for the first discovered sensor - - sensor_handle = sensors[0].handle; // Assuming at least one sensor is available - - status = ocre_sensors_open_channel(&sensor_handle); - - if (status != 0) { - - printf("Failed to open sensor channel. Status: %d\n", status); - - return; - - } - - - -// Step 4: Read a sample from the sensor - - ocre_sensors_sample_t sample = sensor_read_sample(&sensor_handle); - - sensor_channel_t temperature = sensor_get_channel(sample, SENSOR_CHANNEL_TEMPERATURE); - - printf("Current temperature: %d\n", temperature); - - - -// Step 5: Set a trigger on the temperature channel - -status = ocre_sensors_set_trigger(sensor_handle, SENSOR_CHANNEL_TEMPERATURE, DATA_READY, my_callback, &subscription_id); - - if (status != 0) { - - printf("Failed to set trigger. Status: %d\n", status); - - return; - - } - - - -// Simulate waiting for trigger events (replace with actual logic as needed) - - k_sleep(K_SECONDS(10)); // Wait for 10 seconds to allow triggers to occur - - - -// Step 6: Clear the trigger subscription - - status = ocre_sensors_clear_trigger(sensor_handle, SENSOR_CHANNEL_TEMPERATURE, subscription_id); - - if (status != 0) { - - printf("Failed to clear trigger. Status: %d\n", status); - - return; - - } - - - -// Step 7: Clean up the sensors environment - - status = ocre_sensors_cleanup(); - - if (status != 0) { - - printf("Failed to clean up sensors. Status: %d\n", status); - - return; - - } - - - - printf("Sensor operations completed successfully.\n"); - -} -``` \ No newline at end of file From 1d06b9f653e7e3d5d0a884d846513fa5a5d4b256 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 8 Jan 2026 13:41:05 +0100 Subject: [PATCH 232/234] fix(zephyr): selection of WAMR architecture Fix the selection of the WAMR architecture based on more robust Zephyr configuration variables. This enables proper support for ARM M33+ boards. Signed-off-by: Marco Casaroli --- zephyr/wamr.cmake | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/zephyr/wamr.cmake b/zephyr/wamr.cmake index 6aeb36c5..aa311b01 100644 --- a/zephyr/wamr.cmake +++ b/zephyr/wamr.cmake @@ -4,18 +4,27 @@ # SPDX-License-Identifier: Apache-2.0 # Determine the ISA of the target and set appropriately + if (DEFINED CONFIG_ISA_THUMB2) + set (TARGET_ISA THUMBV8M) +elseif (DEFINED CONFIG_CPU_CORTEX_M) set(TARGET_ISA THUMB) -elseif (DEFINED CONFIG_ISA_ARM) - set(TARGET_ISA ARM) elseif (DEFINED CONFIG_ARM64) set(TARGET_ISA AARCH64) +elseif (DEFINED CONFIG_ISA_ARM) + set(TARGET_ISA ARM) +elseif (DEFINED CONFIG_X86_64) + set(TARGET_ISA X86_64) elseif (DEFINED CONFIG_X86) set(TARGET_ISA X86_32) elseif (DEFINED CONFIG_XTENSA) set(TARGET_ISA XTENSA) elseif (DEFINED CONFIG_RISCV) - set(TARGET_ISA RISCV32) + if (DEFINED CONFIG_64BIT) + set(TARGET_ISA RISCV64) + else() + set(TARGET_ISA RISCV32) + endif() elseif (DEFINED CONFIG_ARCH_POSIX) execute_process( COMMAND uname -m From 0628ac357bf8f2f5304c9ae8052af8a3b6389202 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Fri, 9 Jan 2026 10:58:41 +0100 Subject: [PATCH 233/234] feat(wamr): rename to wamr/wasip1 To be more explicit about the environment, as we will have other WAMR based non-wasi engines also in the future. Signed-off-by: Marco Casaroli --- CMakeLists.txt | 2 +- src/ocre/ocre.c | 2 +- .../{wamr => wamr-wasip1}/CMakeLists.txt | 0 .../include/ocre/runtime/wamr/wasip1.h} | 0 .../ocre_api/CMakeLists.txt | 0 .../ocre_api/core/core_eventq.c | 0 .../ocre_api/core/core_external.h | 0 .../ocre_api/core/core_internal.h | 0 .../ocre_api/core/core_memory.c | 0 .../ocre_api/core/core_misc.c | 0 .../ocre_api/core/core_mutex.c | 0 .../ocre_api/core/core_timer.c | 0 .../{wamr => wamr-wasip1}/ocre_api/ocre_api.c | 0 .../{wamr => wamr-wasip1}/ocre_api/ocre_api.h | 0 .../ocre_api/ocre_common.c | 0 .../ocre_api/ocre_common.h | 0 .../ocre_api/ocre_gpio/ocre_gpio.c | 0 .../ocre_api/ocre_gpio/ocre_gpio.h | 0 .../ocre_api/ocre_messaging/ocre_messaging.c | 0 .../ocre_api/ocre_messaging/ocre_messaging.h | 0 .../ocre_sensors/custom,rng-sensor.yaml | 0 .../ocre_api/ocre_sensors/ocre_sensors.c | 0 .../ocre_api/ocre_sensors/ocre_sensors.h | 0 .../ocre_api/ocre_sensors/rng_sensor.c | 0 .../ocre_api/ocre_sensors/rng_sensor.h | 0 .../ocre_api/ocre_timers/ocre_timer.c | 0 .../ocre_api/ocre_timers/ocre_timer.h | 0 .../ocre_api/utils/strlcat.c | 0 .../ocre_api/utils/strlcat.h | 0 src/runtime/{wamr => wamr-wasip1}/wamr.c | 2 +- src/samples/demo/main.c | 9 +-- src/samples/mini/main.c | 2 +- tests/system/container.c | 4 +- tests/system/context.c | 64 +++++++++---------- zephyr/CMakeLists.txt | 2 +- 35 files changed, 44 insertions(+), 43 deletions(-) rename src/runtime/{wamr => wamr-wasip1}/CMakeLists.txt (100%) rename src/runtime/{wamr/include/ocre/runtime/wamr/wamr.h => wamr-wasip1/include/ocre/runtime/wamr/wasip1.h} (100%) rename src/runtime/{wamr => wamr-wasip1}/ocre_api/CMakeLists.txt (100%) rename src/runtime/{wamr => wamr-wasip1}/ocre_api/core/core_eventq.c (100%) rename src/runtime/{wamr => wamr-wasip1}/ocre_api/core/core_external.h (100%) rename src/runtime/{wamr => wamr-wasip1}/ocre_api/core/core_internal.h (100%) rename src/runtime/{wamr => wamr-wasip1}/ocre_api/core/core_memory.c (100%) rename src/runtime/{wamr => wamr-wasip1}/ocre_api/core/core_misc.c (100%) rename src/runtime/{wamr => wamr-wasip1}/ocre_api/core/core_mutex.c (100%) rename src/runtime/{wamr => wamr-wasip1}/ocre_api/core/core_timer.c (100%) rename src/runtime/{wamr => wamr-wasip1}/ocre_api/ocre_api.c (100%) rename src/runtime/{wamr => wamr-wasip1}/ocre_api/ocre_api.h (100%) rename src/runtime/{wamr => wamr-wasip1}/ocre_api/ocre_common.c (100%) rename src/runtime/{wamr => wamr-wasip1}/ocre_api/ocre_common.h (100%) rename src/runtime/{wamr => wamr-wasip1}/ocre_api/ocre_gpio/ocre_gpio.c (100%) rename src/runtime/{wamr => wamr-wasip1}/ocre_api/ocre_gpio/ocre_gpio.h (100%) rename src/runtime/{wamr => wamr-wasip1}/ocre_api/ocre_messaging/ocre_messaging.c (100%) rename src/runtime/{wamr => wamr-wasip1}/ocre_api/ocre_messaging/ocre_messaging.h (100%) rename src/runtime/{wamr => wamr-wasip1}/ocre_api/ocre_sensors/custom,rng-sensor.yaml (100%) rename src/runtime/{wamr => wamr-wasip1}/ocre_api/ocre_sensors/ocre_sensors.c (100%) rename src/runtime/{wamr => wamr-wasip1}/ocre_api/ocre_sensors/ocre_sensors.h (100%) rename src/runtime/{wamr => wamr-wasip1}/ocre_api/ocre_sensors/rng_sensor.c (100%) rename src/runtime/{wamr => wamr-wasip1}/ocre_api/ocre_sensors/rng_sensor.h (100%) rename src/runtime/{wamr => wamr-wasip1}/ocre_api/ocre_timers/ocre_timer.c (100%) rename src/runtime/{wamr => wamr-wasip1}/ocre_api/ocre_timers/ocre_timer.h (100%) rename src/runtime/{wamr => wamr-wasip1}/ocre_api/utils/strlcat.c (100%) rename src/runtime/{wamr => wamr-wasip1}/ocre_api/utils/strlcat.h (100%) rename src/runtime/{wamr => wamr-wasip1}/wamr.c (99%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 626c1c4f..a8fc71a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ add_subdirectory(src/runtime) # runtime include (cmake/wamr.cmake) -add_subdirectory(src/runtime/wamr) +add_subdirectory(src/runtime/wamr-wasip1) # platform add_subdirectory(src/platform/posix) diff --git a/src/ocre/ocre.c b/src/ocre/ocre.c index cfb553ee..6077a1c1 100644 --- a/src/ocre/ocre.c +++ b/src/ocre/ocre.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include "context.h" #include "util/rm_rf.h" diff --git a/src/runtime/wamr/CMakeLists.txt b/src/runtime/wamr-wasip1/CMakeLists.txt similarity index 100% rename from src/runtime/wamr/CMakeLists.txt rename to src/runtime/wamr-wasip1/CMakeLists.txt diff --git a/src/runtime/wamr/include/ocre/runtime/wamr/wamr.h b/src/runtime/wamr-wasip1/include/ocre/runtime/wamr/wasip1.h similarity index 100% rename from src/runtime/wamr/include/ocre/runtime/wamr/wamr.h rename to src/runtime/wamr-wasip1/include/ocre/runtime/wamr/wasip1.h diff --git a/src/runtime/wamr/ocre_api/CMakeLists.txt b/src/runtime/wamr-wasip1/ocre_api/CMakeLists.txt similarity index 100% rename from src/runtime/wamr/ocre_api/CMakeLists.txt rename to src/runtime/wamr-wasip1/ocre_api/CMakeLists.txt diff --git a/src/runtime/wamr/ocre_api/core/core_eventq.c b/src/runtime/wamr-wasip1/ocre_api/core/core_eventq.c similarity index 100% rename from src/runtime/wamr/ocre_api/core/core_eventq.c rename to src/runtime/wamr-wasip1/ocre_api/core/core_eventq.c diff --git a/src/runtime/wamr/ocre_api/core/core_external.h b/src/runtime/wamr-wasip1/ocre_api/core/core_external.h similarity index 100% rename from src/runtime/wamr/ocre_api/core/core_external.h rename to src/runtime/wamr-wasip1/ocre_api/core/core_external.h diff --git a/src/runtime/wamr/ocre_api/core/core_internal.h b/src/runtime/wamr-wasip1/ocre_api/core/core_internal.h similarity index 100% rename from src/runtime/wamr/ocre_api/core/core_internal.h rename to src/runtime/wamr-wasip1/ocre_api/core/core_internal.h diff --git a/src/runtime/wamr/ocre_api/core/core_memory.c b/src/runtime/wamr-wasip1/ocre_api/core/core_memory.c similarity index 100% rename from src/runtime/wamr/ocre_api/core/core_memory.c rename to src/runtime/wamr-wasip1/ocre_api/core/core_memory.c diff --git a/src/runtime/wamr/ocre_api/core/core_misc.c b/src/runtime/wamr-wasip1/ocre_api/core/core_misc.c similarity index 100% rename from src/runtime/wamr/ocre_api/core/core_misc.c rename to src/runtime/wamr-wasip1/ocre_api/core/core_misc.c diff --git a/src/runtime/wamr/ocre_api/core/core_mutex.c b/src/runtime/wamr-wasip1/ocre_api/core/core_mutex.c similarity index 100% rename from src/runtime/wamr/ocre_api/core/core_mutex.c rename to src/runtime/wamr-wasip1/ocre_api/core/core_mutex.c diff --git a/src/runtime/wamr/ocre_api/core/core_timer.c b/src/runtime/wamr-wasip1/ocre_api/core/core_timer.c similarity index 100% rename from src/runtime/wamr/ocre_api/core/core_timer.c rename to src/runtime/wamr-wasip1/ocre_api/core/core_timer.c diff --git a/src/runtime/wamr/ocre_api/ocre_api.c b/src/runtime/wamr-wasip1/ocre_api/ocre_api.c similarity index 100% rename from src/runtime/wamr/ocre_api/ocre_api.c rename to src/runtime/wamr-wasip1/ocre_api/ocre_api.c diff --git a/src/runtime/wamr/ocre_api/ocre_api.h b/src/runtime/wamr-wasip1/ocre_api/ocre_api.h similarity index 100% rename from src/runtime/wamr/ocre_api/ocre_api.h rename to src/runtime/wamr-wasip1/ocre_api/ocre_api.h diff --git a/src/runtime/wamr/ocre_api/ocre_common.c b/src/runtime/wamr-wasip1/ocre_api/ocre_common.c similarity index 100% rename from src/runtime/wamr/ocre_api/ocre_common.c rename to src/runtime/wamr-wasip1/ocre_api/ocre_common.c diff --git a/src/runtime/wamr/ocre_api/ocre_common.h b/src/runtime/wamr-wasip1/ocre_api/ocre_common.h similarity index 100% rename from src/runtime/wamr/ocre_api/ocre_common.h rename to src/runtime/wamr-wasip1/ocre_api/ocre_common.h diff --git a/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.c b/src/runtime/wamr-wasip1/ocre_api/ocre_gpio/ocre_gpio.c similarity index 100% rename from src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.c rename to src/runtime/wamr-wasip1/ocre_api/ocre_gpio/ocre_gpio.c diff --git a/src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.h b/src/runtime/wamr-wasip1/ocre_api/ocre_gpio/ocre_gpio.h similarity index 100% rename from src/runtime/wamr/ocre_api/ocre_gpio/ocre_gpio.h rename to src/runtime/wamr-wasip1/ocre_api/ocre_gpio/ocre_gpio.h diff --git a/src/runtime/wamr/ocre_api/ocre_messaging/ocre_messaging.c b/src/runtime/wamr-wasip1/ocre_api/ocre_messaging/ocre_messaging.c similarity index 100% rename from src/runtime/wamr/ocre_api/ocre_messaging/ocre_messaging.c rename to src/runtime/wamr-wasip1/ocre_api/ocre_messaging/ocre_messaging.c diff --git a/src/runtime/wamr/ocre_api/ocre_messaging/ocre_messaging.h b/src/runtime/wamr-wasip1/ocre_api/ocre_messaging/ocre_messaging.h similarity index 100% rename from src/runtime/wamr/ocre_api/ocre_messaging/ocre_messaging.h rename to src/runtime/wamr-wasip1/ocre_api/ocre_messaging/ocre_messaging.h diff --git a/src/runtime/wamr/ocre_api/ocre_sensors/custom,rng-sensor.yaml b/src/runtime/wamr-wasip1/ocre_api/ocre_sensors/custom,rng-sensor.yaml similarity index 100% rename from src/runtime/wamr/ocre_api/ocre_sensors/custom,rng-sensor.yaml rename to src/runtime/wamr-wasip1/ocre_api/ocre_sensors/custom,rng-sensor.yaml diff --git a/src/runtime/wamr/ocre_api/ocre_sensors/ocre_sensors.c b/src/runtime/wamr-wasip1/ocre_api/ocre_sensors/ocre_sensors.c similarity index 100% rename from src/runtime/wamr/ocre_api/ocre_sensors/ocre_sensors.c rename to src/runtime/wamr-wasip1/ocre_api/ocre_sensors/ocre_sensors.c diff --git a/src/runtime/wamr/ocre_api/ocre_sensors/ocre_sensors.h b/src/runtime/wamr-wasip1/ocre_api/ocre_sensors/ocre_sensors.h similarity index 100% rename from src/runtime/wamr/ocre_api/ocre_sensors/ocre_sensors.h rename to src/runtime/wamr-wasip1/ocre_api/ocre_sensors/ocre_sensors.h diff --git a/src/runtime/wamr/ocre_api/ocre_sensors/rng_sensor.c b/src/runtime/wamr-wasip1/ocre_api/ocre_sensors/rng_sensor.c similarity index 100% rename from src/runtime/wamr/ocre_api/ocre_sensors/rng_sensor.c rename to src/runtime/wamr-wasip1/ocre_api/ocre_sensors/rng_sensor.c diff --git a/src/runtime/wamr/ocre_api/ocre_sensors/rng_sensor.h b/src/runtime/wamr-wasip1/ocre_api/ocre_sensors/rng_sensor.h similarity index 100% rename from src/runtime/wamr/ocre_api/ocre_sensors/rng_sensor.h rename to src/runtime/wamr-wasip1/ocre_api/ocre_sensors/rng_sensor.h diff --git a/src/runtime/wamr/ocre_api/ocre_timers/ocre_timer.c b/src/runtime/wamr-wasip1/ocre_api/ocre_timers/ocre_timer.c similarity index 100% rename from src/runtime/wamr/ocre_api/ocre_timers/ocre_timer.c rename to src/runtime/wamr-wasip1/ocre_api/ocre_timers/ocre_timer.c diff --git a/src/runtime/wamr/ocre_api/ocre_timers/ocre_timer.h b/src/runtime/wamr-wasip1/ocre_api/ocre_timers/ocre_timer.h similarity index 100% rename from src/runtime/wamr/ocre_api/ocre_timers/ocre_timer.h rename to src/runtime/wamr-wasip1/ocre_api/ocre_timers/ocre_timer.h diff --git a/src/runtime/wamr/ocre_api/utils/strlcat.c b/src/runtime/wamr-wasip1/ocre_api/utils/strlcat.c similarity index 100% rename from src/runtime/wamr/ocre_api/utils/strlcat.c rename to src/runtime/wamr-wasip1/ocre_api/utils/strlcat.c diff --git a/src/runtime/wamr/ocre_api/utils/strlcat.h b/src/runtime/wamr-wasip1/ocre_api/utils/strlcat.h similarity index 100% rename from src/runtime/wamr/ocre_api/utils/strlcat.h rename to src/runtime/wamr-wasip1/ocre_api/utils/strlcat.h diff --git a/src/runtime/wamr/wamr.c b/src/runtime/wamr-wasip1/wamr.c similarity index 99% rename from src/runtime/wamr/wamr.c rename to src/runtime/wamr-wasip1/wamr.c index 2ed0d46c..cf724e17 100644 --- a/src/runtime/wamr/wamr.c +++ b/src/runtime/wamr-wasip1/wamr.c @@ -485,7 +485,7 @@ static int instance_destroy(void *runtime_context) } const struct ocre_runtime_vtable wamr_vtable = { - .runtime_name = "wamr", + .runtime_name = "wamr/wasip1", .init = runtime_init, .deinit = runtime_deinit, .create = instance_create, diff --git a/src/samples/demo/main.c b/src/samples/demo/main.c index 05b7a9de..eb209fe9 100644 --- a/src/samples/demo/main.c +++ b/src/samples/demo/main.c @@ -36,7 +36,7 @@ int main(int argc, char *argv[]) } struct ocre_container *hello_world = - ocre_context_create_container(ocre, "hello-world.wasm", "wamr", NULL, false, &args); + ocre_context_create_container(ocre, "hello-world.wasm", "wamr/wasip1", NULL, false, &args); if (!hello_world) { fprintf(stderr, "Failed to create container\n"); @@ -55,7 +55,8 @@ int main(int argc, char *argv[]) return 1; } - struct ocre_container *blinky = ocre_context_create_container(ocre, "blinky.wasm", "wamr", NULL, true, &args); + struct ocre_container *blinky = + ocre_context_create_container(ocre, "blinky.wasm", "wamr/wasip1", NULL, true, &args); if (!blinky) { fprintf(stderr, "Failed to create container\n"); @@ -91,7 +92,7 @@ int main(int argc, char *argv[]) } struct ocre_container *subscriber = - ocre_context_create_container(ocre, "subscriber.wasm", "wamr", NULL, true, &args); + ocre_context_create_container(ocre, "subscriber.wasm", "wamr/wasip1", NULL, true, &args); if (!subscriber) { fprintf(stderr, "Failed to create container\n"); @@ -99,7 +100,7 @@ int main(int argc, char *argv[]) } struct ocre_container *publisher = - ocre_context_create_container(ocre, "publisher.wasm", "wamr", NULL, true, &args); + ocre_context_create_container(ocre, "publisher.wasm", "wamr/wasip1", NULL, true, &args); if (!publisher) { fprintf(stderr, "Failed to create container\n"); diff --git a/src/samples/mini/main.c b/src/samples/mini/main.c index ad43340b..d527c011 100644 --- a/src/samples/mini/main.c +++ b/src/samples/mini/main.c @@ -92,7 +92,7 @@ int main(int argc, char *argv[]) free(sample_path); struct ocre_container *container = - ocre_context_create_container(ocre, "sample.wasm", "wamr", NULL, false, NULL); + ocre_context_create_container(ocre, "sample.wasm", "wamr/wasip1", NULL, false, NULL); if (!container) { fprintf(stderr, "Failed to create container\n"); diff --git a/tests/system/container.c b/tests/system/container.c index a5a79a82..56d30a9c 100644 --- a/tests/system/container.c +++ b/tests/system/container.c @@ -29,8 +29,8 @@ void setUp(void) ocre_initialize(NULL); context = ocre_create_context("./ocre/src/ocre/var/lib/ocre"); - hello_world = ocre_context_create_container(context, "hello-world.wasm", "wamr", "hello", false, NULL); - blinky = ocre_context_create_container(context, "blinky.wasm", "wamr", NULL, true, &args); + hello_world = ocre_context_create_container(context, "hello-world.wasm", "wamr/wasip1", "hello", false, NULL); + blinky = ocre_context_create_container(context, "blinky.wasm", "wamr/wasip1", NULL, true, &args); } void tearDown(void) diff --git a/tests/system/context.c b/tests/system/context.c index bb34b2c6..8eb8822b 100644 --- a/tests/system/context.c +++ b/tests/system/context.c @@ -49,7 +49,7 @@ void test_ocre_context_create_container_null_context(void) { /* Try to create container with bad context */ - TEST_ASSERT_NULL(ocre_context_create_container(NULL, "hello-world.wasm", "wamr", NULL, false, NULL)); + TEST_ASSERT_NULL(ocre_context_create_container(NULL, "hello-world.wasm", "wamr/wasip1", NULL, false, NULL)); } void test_ocre_context_create_container_bad_ids(void) @@ -58,16 +58,16 @@ void test_ocre_context_create_container_bad_ids(void) TEST_ASSERT_NULL(ocre_context_create_container(context, NULL, NULL, NULL, false, NULL)); TEST_ASSERT_NULL(ocre_context_create_container(context, "", "", NULL, false, NULL)); - TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr", ".", false, NULL)); - TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr", "..", false, NULL)); - TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr", "/", false, NULL)); - TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr", "/somewhere", false, NULL)); - TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr", "some/where", false, NULL)); - TEST_ASSERT_NULL(ocre_context_create_container(context, ".", "wamr", NULL, false, NULL)); - TEST_ASSERT_NULL(ocre_context_create_container(context, "..", "wamr", NULL, false, NULL)); - TEST_ASSERT_NULL(ocre_context_create_container(context, "/", "wamr", NULL, false, NULL)); - TEST_ASSERT_NULL(ocre_context_create_container(context, "/somewhere", "wamr", NULL, false, NULL)); - TEST_ASSERT_NULL(ocre_context_create_container(context, "some/where", "wamr", NULL, false, NULL)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr/wasip1", ".", false, NULL)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr/wasip1", "..", false, NULL)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr/wasip1", "/", false, NULL)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr/wasip1", "/somewhere", false, NULL)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr/wasip1", "some/where", false, NULL)); + TEST_ASSERT_NULL(ocre_context_create_container(context, ".", "wamr/wasip1", NULL, false, NULL)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "..", "wamr/wasip1", NULL, false, NULL)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "/", "wamr/wasip1", NULL, false, NULL)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "/somewhere", "wamr/wasip1", NULL, false, NULL)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "some/where", "wamr/wasip1", NULL, false, NULL)); } void test_ocre_context_create_container_bad_runtimes(void) @@ -83,31 +83,31 @@ void test_ocre_context_create_container_bad_mounts(void) bad_mounts.mounts = (const char *[]){"no-colon", NULL}; - TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, &bad_mounts)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr/wasip1", NULL, false, &bad_mounts)); bad_mounts.mounts = (const char *[]){"no_abs_path:/hello", NULL}; - TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, &bad_mounts)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr/wasip1", NULL, false, &bad_mounts)); bad_mounts.mounts = (const char *[]){"/tmp:/", NULL}; - TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, &bad_mounts)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr/wasip1", NULL, false, &bad_mounts)); bad_mounts.mounts = (const char *[]){"/tmp:no_abs", NULL}; - TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, &bad_mounts)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr/wasip1", NULL, false, &bad_mounts)); bad_mounts.mounts = (const char *[]){"/tmp:", NULL}; - TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, &bad_mounts)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr/wasip1", NULL, false, &bad_mounts)); bad_mounts.mounts = (const char *[]){"/tmp", NULL}; - TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, &bad_mounts)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr/wasip1", NULL, false, &bad_mounts)); bad_mounts.mounts = (const char *[]){"/tmp:/ok", "bad", NULL}; - TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, &bad_mounts)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "wamr/wasip1", NULL, false, &bad_mounts)); } void test_ocre_context_remove_bad_container(void) @@ -129,7 +129,7 @@ void test_ocre_context_create_container_ok(void) /* Create a valid container */ struct ocre_container *container = - ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, NULL); + ocre_context_create_container(context, "hello-world.wasm", "wamr/wasip1", NULL, false, NULL); TEST_ASSERT_NOT_NULL(container); /* Check container status */ @@ -146,7 +146,7 @@ void test_ocre_context_create_container_with_id_ok(void) /* Create a valid container */ struct ocre_container *container = - ocre_context_create_container(context, "hello-world.wasm", "wamr", "test-container", false, NULL); + ocre_context_create_container(context, "hello-world.wasm", "wamr/wasip1", "test-container", false, NULL); TEST_ASSERT_NOT_NULL(container); /* Check container status */ @@ -176,7 +176,7 @@ void test_ocre_context_create_start_container_filesystem(void) /* Create a valid container */ struct ocre_container *container = - ocre_context_create_container(context, "filesystem.wasm", "wamr", NULL, false, &args); + ocre_context_create_container(context, "filesystem.wasm", "wamr/wasip1", NULL, false, &args); TEST_ASSERT_NOT_NULL(container); /* Start the container */ @@ -193,13 +193,13 @@ void test_ocre_context_create_container_with_id_twice(void) /* Create a valid container */ struct ocre_container *container = - ocre_context_create_container(context, "hello-world.wasm", "wamr", "test-container", false, NULL); + ocre_context_create_container(context, "hello-world.wasm", "wamr/wasip1", "test-container", false, NULL); TEST_ASSERT_NOT_NULL(container); /* Another container with the same id should fail */ TEST_ASSERT_NULL( - ocre_context_create_container(context, "hello-world.wasm", "wamr", "test-container", false, NULL)); + ocre_context_create_container(context, "hello-world.wasm", "wamr/wasip1", "test-container", false, NULL)); /* Remove the container */ @@ -211,7 +211,7 @@ void test_ocre_context_create_container_and_forget(void) /* Create a valid container */ struct ocre_container *container = - ocre_context_create_container(context, "hello-world.wasm", "wamr", "should-not-leak", false, NULL); + ocre_context_create_container(context, "hello-world.wasm", "wamr/wasip1", "should-not-leak", false, NULL); TEST_ASSERT_NOT_NULL(container); /* Check container status */ @@ -226,7 +226,7 @@ void test_ocre_context_create_wait_remove(void) /* Create a valid container */ struct ocre_container *container = - ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, NULL); + ocre_context_create_container(context, "hello-world.wasm", "wamr/wasip1", NULL, false, NULL); TEST_ASSERT_NOT_NULL(container); /* Check container status */ @@ -256,7 +256,7 @@ void test_ocre_context_create_no_ocre_api(void) /* Create a valid container but it won't work as we don't have ocre:api */ struct ocre_container *container = - ocre_context_create_container(context, "blinky.wasm", "wamr", NULL, true, NULL); + ocre_context_create_container(context, "blinky.wasm", "wamr/wasip1", NULL, true, NULL); TEST_ASSERT_NOT_NULL(container); /* Check container status */ @@ -303,7 +303,7 @@ void test_ocre_context_create_kill_wait_remove(void) /* Create a valid container and have ocre:api*/ struct ocre_container *container = - ocre_context_create_container(context, "blinky.wasm", "wamr", NULL, true, &args); + ocre_context_create_container(context, "blinky.wasm", "wamr/wasip1", NULL, true, &args); TEST_ASSERT_NOT_NULL(container); /* Check container status */ @@ -356,7 +356,7 @@ void test_ocre_context_get_container_count(void) /* Create a valid container */ struct ocre_container *container1 = - ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, NULL); + ocre_context_create_container(context, "hello-world.wasm", "wamr/wasip1", NULL, false, NULL); TEST_ASSERT_NOT_NULL(container1); /* There must be one container */ @@ -366,7 +366,7 @@ void test_ocre_context_get_container_count(void) /* Create another valid container */ struct ocre_container *container2 = - ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, NULL); + ocre_context_create_container(context, "hello-world.wasm", "wamr/wasip1", NULL, false, NULL); TEST_ASSERT_NOT_NULL(container2); /* There must be two containers */ @@ -403,7 +403,7 @@ void test_ocre_context_get_container_by_id_ok(void) /* Create a valid container */ struct ocre_container *container = - ocre_context_create_container(context, "hello-world.wasm", "wamr", "my-id", false, NULL); + ocre_context_create_container(context, "hello-world.wasm", "wamr/wasip1", "my-id", false, NULL); TEST_ASSERT_NOT_NULL(container); /* Get container by ID */ @@ -440,7 +440,7 @@ void test_ocre_context_get_containers_ok(void) /* Create a valid container */ struct ocre_container *container1 = - ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, NULL); + ocre_context_create_container(context, "hello-world.wasm", "wamr/wasip1", NULL, false, NULL); TEST_ASSERT_NOT_NULL(container1); /* There must be one container */ @@ -450,7 +450,7 @@ void test_ocre_context_get_containers_ok(void) /* Create another valid container */ struct ocre_container *container2 = - ocre_context_create_container(context, "hello-world.wasm", "wamr", NULL, false, NULL); + ocre_context_create_container(context, "hello-world.wasm", "wamr/wasip1", NULL, false, NULL); TEST_ASSERT_NOT_NULL(container2); /* There must be two containers */ diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 2f5aa64d..cbadb2e7 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -19,7 +19,7 @@ include (wamr.cmake) add_subdirectory(../src/ocre "ocre-core") add_subdirectory(../src/runtime "ocre-runtime") -add_subdirectory(../src/runtime/wamr "ocre-runtime-wamr") +add_subdirectory(../src/runtime/wamr-wasip1 "ocre-runtime-wamr-wasip1") add_subdirectory(../src/platform/zephyr "ocre-zephyr") if(CONFIG_OCRE_SHELL) message(STATUS "Shell is enabled") From 42243b18baad8594008d531793dc9681d3913c07 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Fri, 9 Jan 2026 11:23:22 +0100 Subject: [PATCH 234/234] feat(container): allow NULL runtime engine In case the user passes a NULL runtime engine, we should try to figure out the correct one, automatically. In the future, we will read this from the container manifest, and let the user override it, however for now, we just use wamr/wasip1 as the "default". Signed-off-by: Marco Casaroli --- src/ocre/container.c | 25 +++++++++++++++++++++++-- src/ocre/include/ocre/context.h | 3 ++- tests/system/context.c | 20 +++++++++++++++++++- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/ocre/container.c b/src/ocre/container.c index 554e3153..0d8cb207 100644 --- a/src/ocre/container.c +++ b/src/ocre/container.c @@ -127,6 +127,22 @@ static ocre_container_status_t ocre_container_status_locked(struct ocre_containe return container->status; } +static char *ocre_find_best_matching_runtime(const char *image) +{ + static const char default_runtime[] = "wamr/wasip1"; + + if (!image) { + LOG_ERR("Image name cannot be NULL"); + return NULL; + } + + /* TODO: find the runtime engine from the image manifest, and return the appropriate one */ + + /* For now, we use "wamr/wasip1" as default */ + + return default_runtime; +} + struct ocre_container *ocre_container_create(const char *img_path, const char *workdir, const char *runtime, const char *container_id, bool detached, const struct ocre_container_args *arguments) @@ -136,8 +152,13 @@ struct ocre_container *ocre_container_create(const char *img_path, const char *w const char **mounts = NULL; if (!runtime) { - LOG_ERR("Runtime is required"); - return NULL; + runtime = ocre_find_best_matching_runtime(img_path); + if (!runtime) { + LOG_ERR("Failed to find best matching runtime engine. Please specify a valid runtime engine."); + return NULL; + } + + LOG_INF("Selected runtime engine: %s", runtime); } /* Check mounts parameters of format : diff --git a/src/ocre/include/ocre/context.h b/src/ocre/include/ocre/context.h index a90ad0c1..9f7f85e3 100644 --- a/src/ocre/include/ocre/context.h +++ b/src/ocre/include/ocre/context.h @@ -124,7 +124,8 @@ struct ocre_container_args { * * @param context A pointer to the context in which to create the container * @param image The name of the image to use for the container - * @param runtime The name of the runtime engine to use for the container + * @param runtime The name of the runtime engine to use for the container. Can be NULL, in which case Ocre will attempt + * to autoatically determine the best runtime for the image. * @param container_id The ID to assign to the container. Can be NULL, in which case a random ID will be generated * @param detached Whether the container should be detached (run in the background) or not * @param arguments The container arguments to pass to the container. Can be NULL diff --git a/tests/system/context.c b/tests/system/context.c index 8eb8822b..7cda3b44 100644 --- a/tests/system/context.c +++ b/tests/system/context.c @@ -74,7 +74,7 @@ void test_ocre_context_create_container_bad_runtimes(void) { TEST_ASSERT_NULL( ocre_context_create_container(context, "hello-world.wasm", "does-not-exit", NULL, false, NULL)); - TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", NULL, NULL, false, NULL)); + TEST_ASSERT_NULL(ocre_context_create_container(context, "hello-world.wasm", "", NULL, false, NULL)); } void test_ocre_context_create_container_bad_mounts(void) @@ -141,6 +141,23 @@ void test_ocre_context_create_container_ok(void) TEST_ASSERT_EQUAL_INT(0, ocre_context_remove_container(context, container)); } +void test_ocre_context_create_container_null_runtime_ok(void) +{ + /* Create a valid container */ + + struct ocre_container *container = + ocre_context_create_container(context, "hello-world.wasm", NULL, NULL, false, NULL); + TEST_ASSERT_NOT_NULL(container); + + /* Check container status */ + + TEST_ASSERT_EQUAL_INT(OCRE_CONTAINER_STATUS_CREATED, ocre_container_get_status(container)); + + /* Remove the container */ + + TEST_ASSERT_EQUAL_INT(0, ocre_context_remove_container(context, container)); +} + void test_ocre_context_create_container_with_id_ok(void) { /* Create a valid container */ @@ -495,6 +512,7 @@ int main(void) RUN_TEST(test_ocre_context_remove_bad_container); RUN_TEST(test_ocre_context_remove_bad_context); RUN_TEST(test_ocre_context_create_container_ok); + RUN_TEST(test_ocre_context_create_container_null_runtime_ok); RUN_TEST(test_ocre_context_create_container_with_id_ok); RUN_TEST(test_ocre_context_create_container_with_id_twice); RUN_TEST(test_ocre_context_create_container_and_forget);