Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Valgrind and Thread Sanitizer (TSan) instrumentation #886

Open
vinser52 opened this issue Nov 11, 2024 · 1 comment
Open

Valgrind and Thread Sanitizer (TSan) instrumentation #886

vinser52 opened this issue Nov 11, 2024 · 1 comment
Labels
bug Something isn't working

Comments

@vinser52
Copy link
Contributor

During the investigation of the CI valgrind failures of PR #736, the concern raised in my mind if we correctly instrumented atomic-store-with-release and atomic-load-with-acquire operations.

Current instrumentation in UMF

In utils_concurrency.h there are two macros:

#define utils_atomic_load_acquire(object, dest)                                \
    do {                                                                       \
        utils_annotate_acquire((void *)object);                                \
        __atomic_load(object, dest, memory_order_acquire);                     \
    } while (0)

#define utils_atomic_store_release(object, desired)                            \
    do {                                                                       \
        __atomic_store_n(object, desired, memory_order_release);               \
        utils_annotate_release((void *)object);                                \
    } while (0)

The utils_annotate_acquire and utils_annotate_release functions defined in the utils_sanitizers.h as follows:

static inline void utils_annotate_acquire(void *ptr) {
#if __SANITIZE_THREAD__
    __tsan_acquire(ptr);
#elif UMF_VG_HELGRIND_ENABLED || UMF_VG_DRD_ENABLED
    ANNOTATE_HAPPENS_AFTER(ptr);
#else
    (void)ptr;
#endif
}

static inline void utils_annotate_release(void *ptr) {
#if __SANITIZE_THREAD__
    __tsan_release(ptr);
#elif UMF_VG_HELGRIND_ENABLED || UMF_VG_DRD_ENABLED
    ANNOTATE_HAPPENS_BEFORE(ptr);
#else
    (void)ptr;
#endif
}

My understanding of Annotation Placement:

Note: My understanding after searching in internet

  1. For Valgrind (using ANNOTATE_HAPPENS_BEFORE and ANNOTATE_HAPPENS_AFTER):
  • ANNOTATE_HAPPENS_BEFORE should be placed immediately before the actual atomic-store-with-release.
  • ANNOTATE_HAPPENS_AFTER should be placed immediately after the actual atomic_load with acquire semantics.
  1. For Thread Sanitizer (TSan) (using __tsan_release and __tsan_acquire):
  • __tsan_release should be placed immediately after the actual atomic_store with release semantics.
  • __tsan_acquire should be placed immediately after the actual atomic_load with acquire semantics.
@vinser52 vinser52 added the bug Something isn't working label Nov 11, 2024
@igchor
Copy link
Member

igchor commented Nov 13, 2024

It looks like the utils_annotate_* calls are actually placed incorrectly in those wrappers. I believe utils_annotate_acquire should be placed AFTER load and release BEFORE the store.

The behavior for TSAN's release/acquire seems to be the same as for Valgrind's BEFORE/AFTER, see here: https://github.com/llvm-mirror/compiler-rt/blob/69445f095c22aac2388f939bedebf224a6efcdaf/lib/tsan/tests/rtl/tsan_mutex.cpp#L189

We also have some places that just call utils_annotate_acquire/release manually, but they look OK (I might have missed something though).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants