Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/lsan-suppressions.txt

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I might be wrong on this but if the OpenCL runtime manages all allocations then all SYCL-related leaks will happen inside the runtime. If we suppress this then we won't get any leak reports caused by wrong runtime usage by the C++ shims/Rust bindings.

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

# Intel GPU OpenCL driver initialization allocations.
leak:libigdrcl.so

# Intel OpenCL adapter queue/event/context leaks reported at process exit.
leak:libur_adapter_opencl.so
22 changes: 22 additions & 0 deletions .github/tsan-suppressions.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Prebuilt Intel CPU OpenCL runtime: worker mutex publication and JIT memset
# versus allocation. Reproduced with a pure C++ queue.memset(...).wait().
# The exact libc++ mutex symbol is bundled in libintelocl; TSan cannot restrict
# a symbol match to that module, so this also excludes other libc++ mutex::lock calls.
race:^std::__1::mutex::lock()$
race:^Intel::OpenCL::Utils::clAllocateFromHeap(

# Prebuilt SYCL runtime: host-task completion versus event/queue destruction.
# Reproduced in pure C++ even with queue.wait() before destruction. Internal
# atomic shared_ptr synchronization is not visible to TSan in these binaries.
race:^sycl::_V1::detail::Scheduler::NotifyHostTaskCompletion(
race:^sycl::_V1::detail::event_impl::cleanupDependencyEvents(
race:^sycl::_V1::detail::Command::~Command(

# Native-only reproduction: copy a host-task event, wait, then release the queue
# and event copies. The native event destructor frees a shared_ptr control block
# whose preceding reference-count decrement was in instrumented application code.
race:^sycl::_V1::detail::event_impl::~event_impl(

# Keep these symbol-scoped: never suppress all of libsycl, the OpenCL adapter,
# free, memset, pthread calls, or the Rust/C++ shim. Revalidate on toolkit updates
# and remove entries when TSan-instrumented native runtimes are available.
63 changes: 63 additions & 0 deletions .github/workflows/basic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,69 @@ jobs:
name: documentation
path: target/doc

hardening:
if: github.event_name != 'schedule'
runs-on: ["oneapi-rs", "Linux"]

steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

- name: Setup oneAPI
uses: ./.github/actions/setup-oneapi

- name: Install nightly toolchain
run: rustup toolchain install nightly --profile minimal

- name: Build and test with hardening flags
env:
RUSTFLAGS: -Zemit-stack-sizes -Zcf-protection=full
CARGO_TARGET_DIR: target/hardened
run: |
cargo +nightly test --workspace --verbose
cargo +nightly build --workspace --release --verbose

sanitizers:
name: Sanitizer (${{ matrix.sanitizer }})
if: github.event_name != 'schedule'
runs-on: ["oneapi-rs", "Linux"]
strategy:
fail-fast: false
matrix:
sanitizer: [address, leak, thread]
env:
CARGO_TARGET_DIR: target/sanitizer-${{ matrix.sanitizer }}

steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

- name: Setup oneAPI
uses: ./.github/actions/setup-oneapi

- name: Install nightly toolchain
run: rustup toolchain install nightly --profile minimal

- name: Install standard library sources for ThreadSanitizer
if: matrix.sanitizer == 'thread'
run: rustup component add rust-src --toolchain nightly

- name: Run tests with sanitizers
env:
# Test only CPU to avoid issues with GPU drivers and sanitizers
ONEAPI_DEVICE_SELECTOR: opencl:cpu
# Leave leak detection to the dedicated leak sanitizer job.
ASAN_OPTIONS: detect_leaks=0
LSAN_OPTIONS: suppressions=${{ github.workspace }}/.github/lsan-suppressions.txt
TSAN_OPTIONS: suppressions=${{ github.workspace }}/.github/tsan-suppressions.txt
RUSTFLAGS: -Zsanitizer=${{ matrix.sanitizer }}
run: |
if [ "${{ matrix.sanitizer }}" = thread ]; then
# Instrument the C++ host shim, not SYCL device code.
export CXX=icpx
export CXXFLAGS="-Xarch_host -fsanitize=thread"
fi
cargo +nightly test ${{ matrix.sanitizer == 'thread' && '-Zbuild-std' || '' }} \
--workspace --lib --tests --target x86_64-unknown-linux-gnu --verbose

trivy:
name: Trivy scan
runs-on: ubuntu-latest
Expand Down
5 changes: 5 additions & 0 deletions sycl/sycl-rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@
//! [`Queue`](crate::queue::Queue) directly. To do the same asynchronously you have to `.await` an
//! event returned by [`Queue::barrier()`](crate::queue::Queue::barrier).
//!
//! Dropping an enqueued allocation or its future (including a losing `tokio::select!` branch)
//! blocks until initialization completes before freeing its memory. Other events and queues do not
//! wait on drop. If an initialization wait fails, the allocation is leaked to avoid freeing memory
//! still in use; explicit wait/await returns the error, while cancellation during drop panics.
//!
//! All basic SYCL wrapper types (`Queue`, `Event`, `Context`, `Platform`, `Device`) are thread safe as
//! indicated by the provided [`Send`] and [`Sync`] trait implementations. However - `UsmBox`es are
//! not thread-safe. If you need a thread-safe `UsmBox` you need to wrap it in an `Arc<Mutex<T>>`.
Expand Down
Loading
Loading