diff options
author | Ivan Maidanski <ivmai@mail.ru> | 2017-11-22 01:05:13 +0300 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2017-11-22 01:05:13 +0300 |
commit | 20468dd131d82be7422aea3c7383ec9201452fce (patch) | |
tree | 4bf7cb4f4910596e85b7da77d672c5e097b4abb1 /mallocx.c | |
parent | 5217c1158cadb8ace825eba764a0f9fd7b72aa63 (diff) | |
download | bdwgc-20468dd131d82be7422aea3c7383ec9201452fce.tar.gz |
Workaround TSan false positive about clear_hdr_marks/realloc data race
* mallocx.c (hb_sz_async_grow_within_hblk): New static function (with
GC_ATTR_NO_SANITIZE_THREAD attribute).
* mallocx.c (GC_realloc): Call hb_sz_async_grow_within_hblk instead of
hhdr->hb_sz=sz.
Diffstat (limited to 'mallocx.c')
-rw-r--r-- | mallocx.c | 14 |
1 files changed, 13 insertions, 1 deletions
@@ -78,6 +78,18 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_generic_or_special_malloc(size_t lb, } } +/* There could be a data race between this function (called from */ +/* GC_realloc without any synchronization) and e.g. GC_clear_hdr_marks */ +/* (invoked indirectly from GC_try_to_collect_inner) but it should be */ +/* safe as long as the new size is not smaller than the old one. */ +GC_ATTR_NO_SANITIZE_THREAD +static void hb_sz_async_grow_within_hblk(hdr * hhdr, size_t sz) +{ + GC_ASSERT(hhdr->hb_sz <= sz + && sz <= ((hhdr->hb_sz + HBLKSIZE - 1) & ~HBLKMASK)); + hhdr->hb_sz = sz; +} + /* Change the size of the block pointed to by p to contain at least */ /* lb bytes. The object may be (and quite likely will be) moved. */ /* The kind (e.g. atomic) is the same as that of the old. */ @@ -109,7 +121,7 @@ GC_API void * GC_CALL GC_realloc(void * p, size_t lb) word descr; sz = (sz+HBLKSIZE-1) & (~HBLKMASK); - hhdr -> hb_sz = sz; + hb_sz_async_grow_within_hblk(hhdr, sz); descr = GC_obj_kinds[obj_kind].ok_descriptor; if (GC_obj_kinds[obj_kind].ok_relocate_descr) descr += sz; hhdr -> hb_descr = descr; |