mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-05-08 20:56:13 +00:00
Add internal tests for WASI threads (#1963)
Add internal tests for WASI threads. These tests are run in addition to the ones in the proposal: https://github.com/WebAssembly/wasi-threads/tree/main/test/testsuite. The purpose is to test additional and more complex scenarios.
This commit is contained in:
parent
289fc5efbf
commit
128c0ea899
|
@ -457,6 +457,10 @@ jobs:
|
||||||
$THREADS_TEST_OPTIONS,
|
$THREADS_TEST_OPTIONS,
|
||||||
$WASI_TEST_OPTIONS,
|
$WASI_TEST_OPTIONS,
|
||||||
]
|
]
|
||||||
|
wasi_sdk_release:
|
||||||
|
[
|
||||||
|
"https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz",
|
||||||
|
]
|
||||||
llvm_cache_key:
|
llvm_cache_key:
|
||||||
["${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }}"]
|
["${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }}"]
|
||||||
exclude:
|
exclude:
|
||||||
|
@ -493,6 +497,31 @@ jobs:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: download and install wasi-sdk
|
||||||
|
if: matrix.test_option == '$WASI_TEST_OPTIONS'
|
||||||
|
run: |
|
||||||
|
cd /opt
|
||||||
|
sudo wget ${{ matrix.wasi_sdk_release }}
|
||||||
|
sudo tar -xzf wasi-sdk-*.tar.gz
|
||||||
|
sudo mv wasi-sdk-19.0 wasi-sdk
|
||||||
|
|
||||||
|
- name: build wasi-libc (needed for wasi-threads)
|
||||||
|
if: matrix.test_option == '$WASI_TEST_OPTIONS'
|
||||||
|
run: |
|
||||||
|
mkdir wasi-libc
|
||||||
|
cd wasi-libc
|
||||||
|
git init
|
||||||
|
# "Rename thread_spawn import" commit on main branch
|
||||||
|
git fetch https://github.com/WebAssembly/wasi-libc \
|
||||||
|
8f5275796a82f8ecfd0833a4f3f444fa37ed4546
|
||||||
|
git checkout FETCH_HEAD
|
||||||
|
make \
|
||||||
|
AR=/opt/wasi-sdk/bin/llvm-ar \
|
||||||
|
NM=/opt/wasi-sdk/bin/llvm-nm \
|
||||||
|
CC=/opt/wasi-sdk/bin/clang \
|
||||||
|
THREAD_MODEL=posix
|
||||||
|
working-directory: core/deps
|
||||||
|
|
||||||
- name: set env variable(if llvm are used)
|
- name: set env variable(if llvm are used)
|
||||||
if: matrix.running_mode == 'aot' || matrix.running_mode == 'jit' || matrix.running_mode == 'multi-tier-jit'
|
if: matrix.running_mode == 'aot' || matrix.running_mode == 'jit' || matrix.running_mode == 'multi-tier-jit'
|
||||||
run: echo "USE_LLVM=true" >> $GITHUB_ENV
|
run: echo "USE_LLVM=true" >> $GITHUB_ENV
|
||||||
|
@ -526,6 +555,11 @@ jobs:
|
||||||
if: matrix.running_mode == 'aot' && matrix.test_option == '$WASI_TEST_OPTIONS'
|
if: matrix.running_mode == 'aot' && matrix.test_option == '$WASI_TEST_OPTIONS'
|
||||||
run: sudo apt-get update && sudo apt install -y jq
|
run: sudo apt-get update && sudo apt install -y jq
|
||||||
|
|
||||||
|
- name: Build WASI thread tests
|
||||||
|
if: matrix.test_option == '$WASI_TEST_OPTIONS'
|
||||||
|
run: WASI_SYSROOT=../../../../../core/deps/wasi-libc/sysroot bash build.sh
|
||||||
|
working-directory: ./core/iwasm/libraries/lib-wasi-threads/test/
|
||||||
|
|
||||||
- name: run tests
|
- name: run tests
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
run: ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }}
|
run: ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }}
|
||||||
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -13,6 +13,7 @@
|
||||||
core/deps/**
|
core/deps/**
|
||||||
core/shared/mem-alloc/tlsf
|
core/shared/mem-alloc/tlsf
|
||||||
core/app-framework/wgl
|
core/app-framework/wgl
|
||||||
|
core/iwasm/libraries/lib-wasi-threads/test/*.wasm
|
||||||
|
|
||||||
wamr-sdk/out/
|
wamr-sdk/out/
|
||||||
wamr-sdk/runtime/build_runtime_sdk/
|
wamr-sdk/runtime/build_runtime_sdk/
|
||||||
|
@ -35,3 +36,5 @@ tests/benchmarks/coremark/coremark*
|
||||||
|
|
||||||
samples/workload/include/**
|
samples/workload/include/**
|
||||||
!samples/workload/include/.gitkeep
|
!samples/workload/include/.gitkeep
|
||||||
|
|
||||||
|
# core/iwasm/libraries/wasi-threads
|
30
core/iwasm/libraries/lib-wasi-threads/test/build.sh
Normal file
30
core/iwasm/libraries/lib-wasi-threads/test/build.sh
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
#
|
||||||
|
|
||||||
|
CC=${CC:=/opt/wasi-sdk/bin/clang}
|
||||||
|
WASI_SYSROOT=${WASI_SYSROOT:=~/dev/wasi-libc/sysroot}
|
||||||
|
WAMR_DIR=../../../../..
|
||||||
|
|
||||||
|
for test_c in *.c; do
|
||||||
|
test_wasm="$(basename $test_c .c).wasm"
|
||||||
|
|
||||||
|
echo "Compiling $test_c to $test_wasm"
|
||||||
|
$CC \
|
||||||
|
--sysroot $WASI_SYSROOT \
|
||||||
|
-target wasm32-wasi-threads \
|
||||||
|
-pthread -ftls-model=local-exec \
|
||||||
|
-z stack-size=32768 \
|
||||||
|
-Wl,--export=__heap_base \
|
||||||
|
-Wl,--export=__data_end \
|
||||||
|
-Wl,--shared-memory,--max-memory=1966080 \
|
||||||
|
-Wl,--export=wasi_thread_start \
|
||||||
|
-Wl,--export=malloc \
|
||||||
|
-Wl,--export=free \
|
||||||
|
-I $WAMR_DIR/samples/wasi-threads/wasm-apps \
|
||||||
|
$WAMR_DIR/samples/wasi-threads/wasm-apps/wasi_thread_start.S \
|
||||||
|
$test_c -o $test_wasm
|
||||||
|
done
|
122
core/iwasm/libraries/lib-wasi-threads/test/common.h
Normal file
122
core/iwasm/libraries/lib-wasi-threads/test/common.h
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2022 Amazon.com Inc. or its affiliates. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "wasi_thread_start.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
BLOCKING_TASK_BUSY_WAIT,
|
||||||
|
BLOCKING_TASK_ATOMIC_WAIT,
|
||||||
|
BLOCKING_TASK_POLL_ONEOFF
|
||||||
|
} blocking_task_type_t;
|
||||||
|
|
||||||
|
/* Parameter to change test behavior */
|
||||||
|
static bool termination_by_trap;
|
||||||
|
static bool termination_in_main_thread;
|
||||||
|
static blocking_task_type_t blocking_task_type;
|
||||||
|
|
||||||
|
#define TIMEOUT_SECONDS 10ll
|
||||||
|
#define NUM_THREADS 3
|
||||||
|
static pthread_barrier_t barrier;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
start_args_t base;
|
||||||
|
bool throw_exception;
|
||||||
|
} shared_t;
|
||||||
|
|
||||||
|
void
|
||||||
|
run_long_task()
|
||||||
|
{
|
||||||
|
if (blocking_task_type == BLOCKING_TASK_BUSY_WAIT) {
|
||||||
|
for (int i = 0; i < TIMEOUT_SECONDS; i++)
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
else if (blocking_task_type == BLOCKING_TASK_ATOMIC_WAIT) {
|
||||||
|
__builtin_wasm_memory_atomic_wait32(
|
||||||
|
0, 0, TIMEOUT_SECONDS * 1000 * 1000 * 1000);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sleep(TIMEOUT_SECONDS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
start_job()
|
||||||
|
{
|
||||||
|
/* Wait for all threads (including the main thread) to be ready */
|
||||||
|
pthread_barrier_wait(&barrier);
|
||||||
|
run_long_task(); /* Task to be interrupted */
|
||||||
|
assert(false && "Thread termination test failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
terminate_process()
|
||||||
|
{
|
||||||
|
/* Wait for all threads (including the main thread) to be ready */
|
||||||
|
pthread_barrier_wait(&barrier);
|
||||||
|
|
||||||
|
if (termination_by_trap)
|
||||||
|
__builtin_trap();
|
||||||
|
else
|
||||||
|
__wasi_proc_exit(33);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
__wasi_thread_start_C(int thread_id, int *start_arg)
|
||||||
|
{
|
||||||
|
shared_t *data = (shared_t *)start_arg;
|
||||||
|
|
||||||
|
if (data->throw_exception) {
|
||||||
|
terminate_process();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
start_job();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_termination(bool trap, bool main, blocking_task_type_t task_type)
|
||||||
|
{
|
||||||
|
termination_by_trap = trap;
|
||||||
|
termination_in_main_thread = main;
|
||||||
|
blocking_task_type = task_type;
|
||||||
|
|
||||||
|
int thread_id = -1, i;
|
||||||
|
shared_t data[NUM_THREADS] = { 0 };
|
||||||
|
assert(pthread_barrier_init(&barrier, NULL, NUM_THREADS + 1) == 0
|
||||||
|
&& "Failed to init barrier");
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_THREADS; i++) {
|
||||||
|
/* No graceful memory free to simplify the test */
|
||||||
|
assert(start_args_init(&data[i].base)
|
||||||
|
&& "Failed to allocate thread's stack");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a thread that forces termination through trap or `proc_exit` */
|
||||||
|
data[0].throw_exception = !termination_in_main_thread;
|
||||||
|
thread_id = __wasi_thread_spawn(&data[0]);
|
||||||
|
assert(thread_id > 0 && "Failed to create thread");
|
||||||
|
|
||||||
|
/* Create two additional threads to test exception propagation */
|
||||||
|
data[1].throw_exception = false;
|
||||||
|
thread_id = __wasi_thread_spawn(&data[1]);
|
||||||
|
assert(thread_id > 0 && "Failed to create thread");
|
||||||
|
data[2].throw_exception = false;
|
||||||
|
thread_id = __wasi_thread_spawn(&data[2]);
|
||||||
|
assert(thread_id > 0 && "Failed to create thread");
|
||||||
|
|
||||||
|
if (termination_in_main_thread) {
|
||||||
|
terminate_process();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
start_job();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,128 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __wasi__
|
||||||
|
#error This example only compiles to WASM/WASI target
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "wasi_thread_start.h"
|
||||||
|
|
||||||
|
enum CONSTANTS {
|
||||||
|
MAX_NUM_THREADS = 4, /* Should be the same as "--max-threads" */
|
||||||
|
NUM_RETRY = 5,
|
||||||
|
SECOND = 1000 * 1000 * 1000, /* 1 second */
|
||||||
|
TIMEOUT = 10LL * SECOND
|
||||||
|
};
|
||||||
|
|
||||||
|
int g_count = 0;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
start_args_t base;
|
||||||
|
int th_ready;
|
||||||
|
int th_continue;
|
||||||
|
int th_done;
|
||||||
|
bool no_ops;
|
||||||
|
} shared_t;
|
||||||
|
|
||||||
|
void
|
||||||
|
__wasi_thread_start_C(int thread_id, int *start_arg)
|
||||||
|
{
|
||||||
|
shared_t *data = (shared_t *)start_arg;
|
||||||
|
|
||||||
|
if (data->no_ops) {
|
||||||
|
__builtin_wasm_memory_atomic_wait32(NULL, 0, 2 * SECOND);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__atomic_store_n(&data->th_ready, 1, __ATOMIC_SEQ_CST);
|
||||||
|
__builtin_wasm_memory_atomic_notify(&data->th_ready, 1);
|
||||||
|
|
||||||
|
if (__builtin_wasm_memory_atomic_wait32(&data->th_continue, 0, TIMEOUT)
|
||||||
|
== 2) {
|
||||||
|
assert(false && "Wait should not time out");
|
||||||
|
}
|
||||||
|
|
||||||
|
__atomic_fetch_add(&g_count, 1, __ATOMIC_SEQ_CST);
|
||||||
|
|
||||||
|
__atomic_store_n(&data->th_done, 1, __ATOMIC_SEQ_CST);
|
||||||
|
__builtin_wasm_memory_atomic_notify(&data->th_done, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
shared_t data[MAX_NUM_THREADS] = { 0 };
|
||||||
|
int thread_ids[MAX_NUM_THREADS];
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_NUM_THREADS; i++) {
|
||||||
|
assert(start_args_init(&data[i].base));
|
||||||
|
thread_ids[i] = __wasi_thread_spawn(&data[i]);
|
||||||
|
printf("Thread created with id=%d\n", thread_ids[i]);
|
||||||
|
assert(thread_ids[i] > 0 && "Thread creation failed");
|
||||||
|
|
||||||
|
for (int j = 0; j < i; j++) {
|
||||||
|
assert(thread_ids[i] != thread_ids[j] && "Duplicated TIDs");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (__builtin_wasm_memory_atomic_wait32(&data[i].th_ready, 0, TIMEOUT)
|
||||||
|
== 2) {
|
||||||
|
assert(false && "Wait should not time out");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Attempt to create thread when not possible\n");
|
||||||
|
shared_t data_fail = { 0 };
|
||||||
|
assert(start_args_init(&data_fail.base));
|
||||||
|
int thread_id = __wasi_thread_spawn(&data_fail);
|
||||||
|
start_args_deinit(&data_fail.base);
|
||||||
|
assert(thread_id < 0 && "Thread creation should fail");
|
||||||
|
|
||||||
|
printf("Unlock created threads\n");
|
||||||
|
for (int i = 0; i < MAX_NUM_THREADS; i++) {
|
||||||
|
__atomic_store_n(&data[i].th_continue, 1, __ATOMIC_SEQ_CST);
|
||||||
|
__builtin_wasm_memory_atomic_notify(&data[i].th_continue, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Wait for threads to finish\n");
|
||||||
|
for (int i = 0; i < MAX_NUM_THREADS; i++) {
|
||||||
|
if (__builtin_wasm_memory_atomic_wait32(&data[i].th_done, 0, TIMEOUT)
|
||||||
|
== 2) {
|
||||||
|
assert(false && "Wait should not time out");
|
||||||
|
}
|
||||||
|
|
||||||
|
start_args_deinit(&data[i].base);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Value of count after update: %d\n", g_count);
|
||||||
|
assert(g_count == (MAX_NUM_THREADS)
|
||||||
|
&& "Global count not updated correctly");
|
||||||
|
|
||||||
|
/* --------------------------------------------------- */
|
||||||
|
|
||||||
|
printf("Create new threads without waiting from them to finish\n");
|
||||||
|
shared_t data_no_join[MAX_NUM_THREADS] = { 0 };
|
||||||
|
for (int i = 0; i < MAX_NUM_THREADS; i++) {
|
||||||
|
/* No graceful memory free to simplify the test */
|
||||||
|
assert(start_args_init(&data_no_join[i].base));
|
||||||
|
data_no_join[i].no_ops = true;
|
||||||
|
|
||||||
|
int thread_id = -1;
|
||||||
|
for (int j = 0; j < NUM_RETRY && thread_id < 0; j++) {
|
||||||
|
thread_id = __wasi_thread_spawn(&data_no_join[i]);
|
||||||
|
if (thread_id < 0)
|
||||||
|
__builtin_wasm_memory_atomic_wait32(NULL, 0, SECOND);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Thread created with id=%d\n", thread_id);
|
||||||
|
assert(thread_id > 0 && "Thread creation should succeed");
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
70
core/iwasm/libraries/lib-wasi-threads/test/global_atomic.c
Normal file
70
core/iwasm/libraries/lib-wasi-threads/test/global_atomic.c
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __wasi__
|
||||||
|
#error This example only compiles to WASM/WASI target
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "wasi_thread_start.h"
|
||||||
|
|
||||||
|
enum CONSTANTS {
|
||||||
|
NUM_THREADS = 4,
|
||||||
|
NUM_ITER = 1000,
|
||||||
|
SECOND = 1000 * 1000 * 1000, /* 1 second */
|
||||||
|
TIMEOUT = 10LL * SECOND
|
||||||
|
};
|
||||||
|
|
||||||
|
int g_count = 0;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
start_args_t base;
|
||||||
|
int th_done;
|
||||||
|
} shared_t;
|
||||||
|
|
||||||
|
void
|
||||||
|
__wasi_thread_start_C(int thread_id, int *start_arg)
|
||||||
|
{
|
||||||
|
shared_t *data = (shared_t *)start_arg;
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_ITER; i++)
|
||||||
|
__atomic_fetch_add(&g_count, 1, __ATOMIC_SEQ_CST);
|
||||||
|
|
||||||
|
__atomic_store_n(&data->th_done, 1, __ATOMIC_SEQ_CST);
|
||||||
|
__builtin_wasm_memory_atomic_notify(&data->th_done, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
shared_t data[NUM_THREADS] = { 0 };
|
||||||
|
int thread_ids[NUM_THREADS];
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_THREADS; i++) {
|
||||||
|
assert(start_args_init(&data[i].base));
|
||||||
|
thread_ids[i] = __wasi_thread_spawn(&data[i]);
|
||||||
|
assert(thread_ids[i] > 0 && "Thread creation failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Wait for threads to finish\n");
|
||||||
|
for (int i = 0; i < NUM_THREADS; i++) {
|
||||||
|
if (__builtin_wasm_memory_atomic_wait32(&data[i].th_done, 0, TIMEOUT)
|
||||||
|
== 2) {
|
||||||
|
assert(false && "Wait should not time out");
|
||||||
|
}
|
||||||
|
|
||||||
|
start_args_deinit(&data[i].base);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Value of count after update: %d\n", g_count);
|
||||||
|
assert(g_count == (NUM_THREADS * NUM_ITER)
|
||||||
|
&& "Global count not updated correctly");
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
78
core/iwasm/libraries/lib-wasi-threads/test/global_lock.c
Normal file
78
core/iwasm/libraries/lib-wasi-threads/test/global_lock.c
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __wasi__
|
||||||
|
#error This example only compiles to WASM/WASI target
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include "wasi_thread_start.h"
|
||||||
|
|
||||||
|
enum CONSTANTS {
|
||||||
|
NUM_THREADS = 4,
|
||||||
|
NUM_ITER = 200,
|
||||||
|
SECOND = 1000 * 1000 * 1000, /* 1 second */
|
||||||
|
TIMEOUT = 10LL * SECOND
|
||||||
|
};
|
||||||
|
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
int g_count = 0;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
start_args_t base;
|
||||||
|
int th_done;
|
||||||
|
} shared_t;
|
||||||
|
|
||||||
|
void
|
||||||
|
__wasi_thread_start_C(int thread_id, int *start_arg)
|
||||||
|
{
|
||||||
|
shared_t *data = (shared_t *)start_arg;
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_ITER; i++) {
|
||||||
|
pthread_mutex_lock(&mutex);
|
||||||
|
g_count++;
|
||||||
|
pthread_mutex_unlock(&mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
__atomic_store_n(&data->th_done, 1, __ATOMIC_SEQ_CST);
|
||||||
|
__builtin_wasm_memory_atomic_notify(&data->th_done, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
shared_t data[NUM_THREADS] = { 0 };
|
||||||
|
int thread_ids[NUM_THREADS];
|
||||||
|
|
||||||
|
assert(pthread_mutex_init(&mutex, NULL) == 0 && "Failed to init mutex");
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_THREADS; i++) {
|
||||||
|
assert(start_args_init(&data[i].base));
|
||||||
|
thread_ids[i] = __wasi_thread_spawn(&data[i]);
|
||||||
|
assert(thread_ids[i] > 0 && "Thread creation failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Wait for threads to finish\n");
|
||||||
|
for (int i = 0; i < NUM_THREADS; i++) {
|
||||||
|
if (__builtin_wasm_memory_atomic_wait32(&data[i].th_done, 0, TIMEOUT)
|
||||||
|
== 2) {
|
||||||
|
assert(false && "Wait should not time out");
|
||||||
|
}
|
||||||
|
|
||||||
|
start_args_deinit(&data[i].base);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Value of count after update: %d\n", g_count);
|
||||||
|
assert(g_count == (NUM_THREADS * NUM_ITER)
|
||||||
|
&& "Global count not updated correctly");
|
||||||
|
|
||||||
|
assert(pthread_mutex_destroy(&mutex) == 0 && "Failed to destroy mutex");
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __wasi__
|
||||||
|
#error This example only compiles to WASM/WASI target
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
test_termination(false, true, BLOCKING_TASK_BUSY_WAIT);
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"exit_code": 33
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __wasi__
|
||||||
|
#error This example only compiles to WASM/WASI target
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
test_termination(false, true, BLOCKING_TASK_POLL_ONEOFF);
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"exit_code": 33
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __wasi__
|
||||||
|
#error This example only compiles to WASM/WASI target
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
test_termination(false, true, BLOCKING_TASK_ATOMIC_WAIT);
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"exit_code": 33
|
||||||
|
}
|
16
core/iwasm/libraries/lib-wasi-threads/test/main_trap_busy.c
Normal file
16
core/iwasm/libraries/lib-wasi-threads/test/main_trap_busy.c
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __wasi__
|
||||||
|
#error This example only compiles to WASM/WASI target
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
test_termination(true, true, BLOCKING_TASK_BUSY_WAIT);
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"exit_code": 1
|
||||||
|
}
|
16
core/iwasm/libraries/lib-wasi-threads/test/main_trap_sleep.c
Normal file
16
core/iwasm/libraries/lib-wasi-threads/test/main_trap_sleep.c
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __wasi__
|
||||||
|
#error This example only compiles to WASM/WASI target
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
test_termination(true, true, BLOCKING_TASK_POLL_ONEOFF);
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"exit_code": 1
|
||||||
|
}
|
16
core/iwasm/libraries/lib-wasi-threads/test/main_trap_wait.c
Normal file
16
core/iwasm/libraries/lib-wasi-threads/test/main_trap_wait.c
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __wasi__
|
||||||
|
#error This example only compiles to WASM/WASI target
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
test_termination(true, true, BLOCKING_TASK_ATOMIC_WAIT);
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"exit_code": 1
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __wasi__
|
||||||
|
#error This example only compiles to WASM/WASI target
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
test_termination(false, false, BLOCKING_TASK_BUSY_WAIT);
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"exit_code": 33
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __wasi__
|
||||||
|
#error This example only compiles to WASM/WASI target
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
test_termination(false, false, BLOCKING_TASK_POLL_ONEOFF);
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"exit_code": 33
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __wasi__
|
||||||
|
#error This example only compiles to WASM/WASI target
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
test_termination(false, false, BLOCKING_TASK_ATOMIC_WAIT);
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"exit_code": 33
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __wasi__
|
||||||
|
#error This example only compiles to WASM/WASI target
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
test_termination(true, false, BLOCKING_TASK_BUSY_WAIT);
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"exit_code": 1
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __wasi__
|
||||||
|
#error This example only compiles to WASM/WASI target
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
test_termination(true, false, BLOCKING_TASK_POLL_ONEOFF);
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"exit_code": 1
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __wasi__
|
||||||
|
#error This example only compiles to WASM/WASI target
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
test_termination(true, false, BLOCKING_TASK_ATOMIC_WAIT);
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"exit_code": 1
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __wasi__
|
||||||
|
#error This example only compiles to WASM/WASI target
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "wasi_thread_start.h"
|
||||||
|
|
||||||
|
enum CONSTANTS {
|
||||||
|
NUM_ITER = 50,
|
||||||
|
NUM_RETRY = 5,
|
||||||
|
SECOND = 1000 * 1000 * 1000, /* 1 second */
|
||||||
|
TIMEOUT = 5LL * SECOND
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
start_args_t base;
|
||||||
|
int th_done;
|
||||||
|
} shared_t;
|
||||||
|
|
||||||
|
int g_count = 0;
|
||||||
|
|
||||||
|
void
|
||||||
|
__wasi_thread_start_C(int thread_id, int *start_arg)
|
||||||
|
{
|
||||||
|
shared_t *data = (shared_t *)start_arg;
|
||||||
|
|
||||||
|
g_count++;
|
||||||
|
|
||||||
|
__atomic_store_n(&data->th_done, 1, __ATOMIC_SEQ_CST);
|
||||||
|
__builtin_wasm_memory_atomic_notify(&data->th_done, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
shared_t data = { 0 };
|
||||||
|
assert(start_args_init(&data.base) && "Stack allocation for thread failed");
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_ITER; i++) {
|
||||||
|
data.th_done = 0;
|
||||||
|
|
||||||
|
printf("Creating thread\n");
|
||||||
|
int thread_id = -1;
|
||||||
|
for (int j = 0; j < NUM_RETRY && thread_id < 0; j++) {
|
||||||
|
thread_id = __wasi_thread_spawn(&data);
|
||||||
|
if (thread_id < 0)
|
||||||
|
__builtin_wasm_memory_atomic_wait32(NULL, 0, SECOND);
|
||||||
|
}
|
||||||
|
assert(thread_id > 0 && "Thread creation should succeed");
|
||||||
|
|
||||||
|
printf("Waiting for thread to finish\n");
|
||||||
|
if (__builtin_wasm_memory_atomic_wait32(&data.th_done, 0, TIMEOUT)
|
||||||
|
== 2) {
|
||||||
|
assert(false && "Wait should not time out");
|
||||||
|
}
|
||||||
|
printf("Thread has finished\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(g_count == NUM_ITER && "Count has not been updated correctly");
|
||||||
|
|
||||||
|
start_args_deinit(&data.base);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __wasi__
|
||||||
|
#error This example only compiles to WASM/WASI target
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "wasi_thread_start.h"
|
||||||
|
|
||||||
|
enum CONSTANTS {
|
||||||
|
NUM_THREADS = 4,
|
||||||
|
NUM_ITER = 30,
|
||||||
|
SECOND = 1000 * 1000 * 1000, /* 1 second */
|
||||||
|
TIMEOUT = 10LL * SECOND
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
start_args_t base;
|
||||||
|
int th_done;
|
||||||
|
int *count;
|
||||||
|
int iteration;
|
||||||
|
int *pval;
|
||||||
|
} shared_t;
|
||||||
|
|
||||||
|
int *vals[NUM_THREADS];
|
||||||
|
|
||||||
|
void
|
||||||
|
__wasi_thread_start_C(int thread_id, int *start_arg)
|
||||||
|
{
|
||||||
|
shared_t *data = (shared_t *)start_arg;
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_ITER; i++)
|
||||||
|
__atomic_fetch_add(data->count, 1, __ATOMIC_SEQ_CST);
|
||||||
|
|
||||||
|
vals[data->iteration] = malloc(sizeof(int));
|
||||||
|
*vals[data->iteration] = data->iteration;
|
||||||
|
|
||||||
|
__atomic_store_n(&data->th_done, 1, __ATOMIC_SEQ_CST);
|
||||||
|
__builtin_wasm_memory_atomic_notify(&data->th_done, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
shared_t data[NUM_THREADS] = { 0 };
|
||||||
|
int thread_ids[NUM_THREADS];
|
||||||
|
int *count = calloc(1, sizeof(int));
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_THREADS; i++) {
|
||||||
|
assert(start_args_init(&data[i].base)
|
||||||
|
&& "Stack allocation for thread failed");
|
||||||
|
__atomic_store_n(&data[i].count, count, __ATOMIC_SEQ_CST);
|
||||||
|
data[i].iteration = i;
|
||||||
|
|
||||||
|
thread_ids[i] = __wasi_thread_spawn(&data[i]);
|
||||||
|
assert(thread_ids[i] > 0 && "Thread creation failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Wait for threads to finish\n");
|
||||||
|
for (int i = 0; i < NUM_THREADS; i++) {
|
||||||
|
if (__builtin_wasm_memory_atomic_wait32(&data[i].th_done, 0, TIMEOUT)
|
||||||
|
== 2) {
|
||||||
|
assert(false && "Wait should not time out");
|
||||||
|
}
|
||||||
|
|
||||||
|
start_args_deinit(&data[i].base);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(*count == (NUM_THREADS * NUM_ITER) && "Count not updated correctly");
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_THREADS; i++) {
|
||||||
|
printf("val=%d\n", *vals[i]);
|
||||||
|
assert(*vals[i] == i && "Value not updated correctly");
|
||||||
|
free(vals[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(count);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
|
@ -33,7 +33,7 @@ __wasi_thread_start_C(int thread_id, int *start_arg)
|
||||||
data->value += 8;
|
data->value += 8;
|
||||||
printf("Updated value: %d\n", data->value);
|
printf("Updated value: %d\n", data->value);
|
||||||
|
|
||||||
data->th_ready = 1;
|
__atomic_store_n(&data->th_ready, 1, __ATOMIC_SEQ_CST);
|
||||||
__builtin_wasm_memory_atomic_notify(&data->th_ready, 1);
|
__builtin_wasm_memory_atomic_notify(&data->th_ready, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <semaphore.h>
|
#include <pthread.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
#define TIMEOUT_SECONDS 10
|
#define TIMEOUT_SECONDS 10
|
||||||
#define NUM_THREADS 3
|
#define NUM_THREADS 3
|
||||||
static sem_t sem;
|
static pthread_barrier_t barrier;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
start_args_t base;
|
start_args_t base;
|
||||||
|
@ -49,9 +49,10 @@ run_long_task()
|
||||||
void
|
void
|
||||||
start_job()
|
start_job()
|
||||||
{
|
{
|
||||||
sem_post(&sem);
|
/* Wait for all threads (including the main thread) to be ready */
|
||||||
run_long_task(); /* Wait to be interrupted */
|
pthread_barrier_wait(&barrier);
|
||||||
assert(false && "Unreachable");
|
run_long_task(); /* Task to be interrupted */
|
||||||
|
assert(false && "Thread termination test failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -59,8 +60,7 @@ terminate_process()
|
||||||
{
|
{
|
||||||
/* Wait for all other threads (including main thread) to be ready */
|
/* Wait for all other threads (including main thread) to be ready */
|
||||||
printf("Waiting before terminating\n");
|
printf("Waiting before terminating\n");
|
||||||
for (int i = 0; i < NUM_THREADS; i++)
|
pthread_barrier_wait(&barrier);
|
||||||
sem_wait(&sem);
|
|
||||||
|
|
||||||
printf("Force termination\n");
|
printf("Force termination\n");
|
||||||
#if TEST_TERMINATION_BY_TRAP == 1
|
#if TEST_TERMINATION_BY_TRAP == 1
|
||||||
|
@ -91,8 +91,8 @@ main(int argc, char **argv)
|
||||||
int thread_id = -1, i;
|
int thread_id = -1, i;
|
||||||
shared_t data[NUM_THREADS] = { 0 };
|
shared_t data[NUM_THREADS] = { 0 };
|
||||||
|
|
||||||
if (sem_init(&sem, 0, 0) != 0) {
|
if (pthread_barrier_init(&barrier, NULL, NUM_THREADS + 1) != 0) {
|
||||||
printf("Failed to init semaphore\n");
|
printf("Failed to init barrier\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ readonly TARGET=$2
|
||||||
|
|
||||||
readonly WORK_DIR=$PWD
|
readonly WORK_DIR=$PWD
|
||||||
readonly PLATFORM=$(uname -s | tr A-Z a-z)
|
readonly PLATFORM=$(uname -s | tr A-Z a-z)
|
||||||
|
readonly WAMR_DIR="${WORK_DIR}/../../../.."
|
||||||
readonly IWASM_CMD="${WORK_DIR}/../../../../product-mini/platforms/${PLATFORM}/build/iwasm"
|
readonly IWASM_CMD="${WORK_DIR}/../../../../product-mini/platforms/${PLATFORM}/build/iwasm"
|
||||||
readonly WAMRC_CMD="${WORK_DIR}/../../../../wamr-compiler/build/wamrc"
|
readonly WAMRC_CMD="${WORK_DIR}/../../../../wamr-compiler/build/wamrc"
|
||||||
|
|
||||||
|
@ -21,7 +22,8 @@ if [[ $MODE != "aot" ]];then
|
||||||
-t \
|
-t \
|
||||||
tests/c/testsuite/ \
|
tests/c/testsuite/ \
|
||||||
tests/assemblyscript/testsuite/ \
|
tests/assemblyscript/testsuite/ \
|
||||||
tests/proposals/wasi-threads/
|
tests/proposals/wasi-threads/ \
|
||||||
|
${WAMR_DIR}/core/iwasm/libraries/lib-wasi-threads/test/
|
||||||
exit_code=${PIPESTATUS[0]}
|
exit_code=${PIPESTATUS[0]}
|
||||||
deactivate
|
deactivate
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in New Issue
Block a user