Trivial changes for thread sanitizer
Thread sanitizer warns about reads and writes of variables that are meant to be read without holding a lock: * Global "keep_going" is now a ddsrt_atomic_uint32_t * Thread "vtime" is now a ddsrt_atomic_uint32_t Previously the code relied on the assumption that a 32-bit int would be treated as atomic, now that is all wrapped in ddsrt_atomic_{ld,st}32. These being inline functions doing exactly the same thing, there is no functional change, but it does allow annotating the loads and stores for via function attributes on the ddsrt_atomic_{ld,st}X. The concurrent hashtable implementation is replaced by a locked version of the non-concurrent implementation if thread sanitizer is used. This changes eliminates the scores of problems signalled by thread sanitizer in the GUID-to-entity translation and the key-to-instance id lookups. Other than that, this replaces a flag used in a waitset test case to be a ddsrt_atomic_uint32_t. Signed-off-by: Erik Boasson <eb@ilities.com>
This commit is contained in:
parent
0356af470d
commit
c6c5a872eb
17 changed files with 404 additions and 267 deletions
|
@ -13,6 +13,7 @@
|
|||
#define DDSRT_ATOMICS_GCC_H
|
||||
|
||||
#include "dds/ddsrt/misc.h"
|
||||
#include "dds/ddsrt/attributes.h"
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
|
@ -25,19 +26,51 @@ extern "C" {
|
|||
|
||||
/* LD, ST */
|
||||
|
||||
inline uint32_t ddsrt_atomic_ld32(const volatile ddsrt_atomic_uint32_t *x) { return x->v; }
|
||||
ddsrt_attribute_no_sanitize (("thread"))
|
||||
inline uint32_t ddsrt_atomic_ld32(const volatile ddsrt_atomic_uint32_t *x)
|
||||
{
|
||||
return x->v;
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline uint64_t ddsrt_atomic_ld64(const volatile ddsrt_atomic_uint64_t *x) { return x->v; }
|
||||
ddsrt_attribute_no_sanitize (("thread"))
|
||||
inline uint64_t ddsrt_atomic_ld64(const volatile ddsrt_atomic_uint64_t *x)
|
||||
{
|
||||
return x->v;
|
||||
}
|
||||
#endif
|
||||
inline uintptr_t ddsrt_atomic_ldptr(const volatile ddsrt_atomic_uintptr_t *x) { return x->v; }
|
||||
inline void *ddsrt_atomic_ldvoidp(const volatile ddsrt_atomic_voidp_t *x) { return (void *) ddsrt_atomic_ldptr(x); }
|
||||
ddsrt_attribute_no_sanitize (("thread"))
|
||||
inline uintptr_t ddsrt_atomic_ldptr(const volatile ddsrt_atomic_uintptr_t *x)
|
||||
{
|
||||
return x->v;
|
||||
}
|
||||
ddsrt_attribute_no_sanitize (("thread"))
|
||||
inline void *ddsrt_atomic_ldvoidp(const volatile ddsrt_atomic_voidp_t *x)
|
||||
{
|
||||
return (void *) ddsrt_atomic_ldptr(x);
|
||||
}
|
||||
|
||||
inline void ddsrt_atomic_st32(volatile ddsrt_atomic_uint32_t *x, uint32_t v) { x->v = v; }
|
||||
ddsrt_attribute_no_sanitize (("thread"))
|
||||
inline void ddsrt_atomic_st32(volatile ddsrt_atomic_uint32_t *x, uint32_t v)
|
||||
{
|
||||
x->v = v;
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline void ddsrt_atomic_st64(volatile ddsrt_atomic_uint64_t *x, uint64_t v) { x->v = v; }
|
||||
ddsrt_attribute_no_sanitize (("thread"))
|
||||
inline void ddsrt_atomic_st64(volatile ddsrt_atomic_uint64_t *x, uint64_t v)
|
||||
{
|
||||
x->v = v;
|
||||
}
|
||||
#endif
|
||||
inline void ddsrt_atomic_stptr(volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) { x->v = v; }
|
||||
inline void ddsrt_atomic_stvoidp(volatile ddsrt_atomic_voidp_t *x, void *v) { ddsrt_atomic_stptr(x, (uintptr_t)v); }
|
||||
ddsrt_attribute_no_sanitize (("thread"))
|
||||
inline void ddsrt_atomic_stptr(volatile ddsrt_atomic_uintptr_t *x, uintptr_t v)
|
||||
{
|
||||
x->v = v;
|
||||
}
|
||||
ddsrt_attribute_no_sanitize (("thread"))
|
||||
inline void ddsrt_atomic_stvoidp(volatile ddsrt_atomic_voidp_t *x, void *v)
|
||||
{
|
||||
ddsrt_atomic_stptr(x, (uintptr_t)v);
|
||||
}
|
||||
|
||||
/* INC */
|
||||
|
||||
|
|
|
@ -111,4 +111,16 @@
|
|||
# define ddsrt_attribute_packed
|
||||
#endif
|
||||
|
||||
#if ddsrt_has_attribute(no_sanitize)
|
||||
# define ddsrt_attribute_no_sanitize(params) __attribute__ ((__no_sanitize__ params))
|
||||
#else
|
||||
# define ddsrt_attribute_no_sanitize(params)
|
||||
#endif
|
||||
|
||||
#if defined(__has_feature)
|
||||
# define ddsrt_has_feature_thread_sanitizer __has_feature(thread_sanitizer)
|
||||
#else
|
||||
# define ddsrt_has_feature_thread_sanitizer 0
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_ATTRIBUTES_H */
|
||||
|
|
|
@ -20,15 +20,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Concurrent version */
|
||||
struct ddsrt_chh;
|
||||
struct ddsrt_chh_bucket;
|
||||
struct ddsrt_chh_iter {
|
||||
struct ddsrt_chh_bucket *bs;
|
||||
uint32_t size;
|
||||
uint32_t cursor;
|
||||
};
|
||||
|
||||
/*
|
||||
* The hopscotch hash table is dependent on a proper functioning hash.
|
||||
* If the hash function generates a lot of hash collisions, then it will
|
||||
|
@ -54,15 +45,6 @@ typedef int (*ddsrt_hh_equals_fn) (const void *, const void *);
|
|||
*/
|
||||
typedef void (*ddsrt_hh_buckets_gc_fn) (void *);
|
||||
|
||||
DDS_EXPORT struct ddsrt_chh *ddsrt_chh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals, ddsrt_hh_buckets_gc_fn gc_buckets);
|
||||
DDS_EXPORT void ddsrt_chh_free (struct ddsrt_chh * __restrict hh);
|
||||
DDS_EXPORT void *ddsrt_chh_lookup (struct ddsrt_chh * __restrict rt, const void * __restrict template);
|
||||
DDS_EXPORT int ddsrt_chh_add (struct ddsrt_chh * __restrict rt, const void * __restrict data);
|
||||
DDS_EXPORT int ddsrt_chh_remove (struct ddsrt_chh * __restrict rt, const void * __restrict template);
|
||||
DDS_EXPORT void ddsrt_chh_enum_unsafe (struct ddsrt_chh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg); /* may delete a */
|
||||
void *ddsrt_chh_iter_first (struct ddsrt_chh * __restrict rt, struct ddsrt_chh_iter *it);
|
||||
void *ddsrt_chh_iter_next (struct ddsrt_chh_iter *it);
|
||||
|
||||
/* Sequential version */
|
||||
struct ddsrt_hh;
|
||||
|
||||
|
@ -80,6 +62,31 @@ DDS_EXPORT void ddsrt_hh_enum (struct ddsrt_hh * __restrict rt, void (*f) (void
|
|||
DDS_EXPORT void *ddsrt_hh_iter_first (struct ddsrt_hh * __restrict rt, struct ddsrt_hh_iter * __restrict iter); /* may delete nodes */
|
||||
DDS_EXPORT void *ddsrt_hh_iter_next (struct ddsrt_hh_iter * __restrict iter);
|
||||
|
||||
/* Concurrent version */
|
||||
struct ddsrt_chh;
|
||||
struct ddsrt_chh_bucket;
|
||||
|
||||
#if ! ddsrt_has_feature_thread_sanitizer
|
||||
struct ddsrt_chh_iter {
|
||||
struct ddsrt_chh_bucket *bs;
|
||||
uint32_t size;
|
||||
uint32_t cursor;
|
||||
};
|
||||
#else
|
||||
struct ddsrt_chh_iter {
|
||||
struct ddsrt_chh *chh;
|
||||
struct ddsrt_hh_iter it;
|
||||
};
|
||||
#endif
|
||||
|
||||
DDS_EXPORT struct ddsrt_chh *ddsrt_chh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals, ddsrt_hh_buckets_gc_fn gc_buckets);
|
||||
DDS_EXPORT void ddsrt_chh_free (struct ddsrt_chh * __restrict hh);
|
||||
DDS_EXPORT void *ddsrt_chh_lookup (struct ddsrt_chh * __restrict rt, const void * __restrict template);
|
||||
DDS_EXPORT int ddsrt_chh_add (struct ddsrt_chh * __restrict rt, const void * __restrict data);
|
||||
DDS_EXPORT int ddsrt_chh_remove (struct ddsrt_chh * __restrict rt, const void * __restrict template);
|
||||
DDS_EXPORT void ddsrt_chh_enum_unsafe (struct ddsrt_chh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg); /* may delete a */
|
||||
DDS_EXPORT void *ddsrt_chh_iter_first (struct ddsrt_chh * __restrict rt, struct ddsrt_chh_iter *it);
|
||||
DDS_EXPORT void *ddsrt_chh_iter_next (struct ddsrt_chh_iter *it);
|
||||
/* Sequential version, embedded data */
|
||||
struct ddsrt_ehh;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue