summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2023-04-27 07:33:50 +0300
committerIvan Maidanski <ivmai@mail.ru>2023-04-27 09:34:32 +0300
commit7334cc94a04bf188762c99b2e4bfc932e508bdc2 (patch)
treed2530e11f3efbac4c1b7e7b6150475f04ec91119
parent430e44c4a37dd2282f58ddc62dc53e43e4bf8724 (diff)
downloadbdwgc-7334cc94a04bf188762c99b2e4bfc932e508bdc2.tar.gz
Eliminate data race FP between remove_protection and write_fault_handler
* os_dep.c [MPROTECT_VDB] (get_pht_entry_from_index_async): Define (as a static function with GC_ATTR_NO_SANITIZE_THREAD or as a macro); add comment. * os_dep.c [!GC_DISABLE_INCREMENTAL && MPROTECT_VDB] (GC_remove_protection): Call get_pht_entry_from_index_async() instead of get_pht_entry_from_index().
-rw-r--r--os_dep.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/os_dep.c b/os_dep.c
index 9b436584..b5d6ef98 100644
--- a/os_dep.c
+++ b/os_dep.c
@@ -3534,6 +3534,22 @@ STATIC void GC_protect_heap(void)
* happens to work.
*/
+# ifdef THREAD_SANITIZER
+ /* Used by GC_remove_protection only. Potential data race between */
+ /* this function and GC_write_fault_handler should not be harmful */
+ /* because it would only result in a double call of UNPROTECT() for */
+ /* a region. */
+ GC_ATTR_NO_SANITIZE_THREAD
+ static GC_bool get_pht_entry_from_index_async(volatile page_hash_table db,
+ size_t index)
+ {
+ return (GC_bool)get_pht_entry_from_index(db, index);
+ }
+# else
+# define get_pht_entry_from_index_async(bl, index) \
+ get_pht_entry_from_index(bl, index)
+# endif
+
/* We no longer wrap read by default, since that was causing too many */
/* problems. It is preferred that the client instead avoids writing */
/* to the write-protected heap with a system call. */
@@ -4245,7 +4261,7 @@ GC_INNER GC_bool GC_dirty_init(void)
h_end = (struct hblk *)(((word)(h + nblocks) + GC_page_size - 1)
& ~(GC_page_size - 1));
if (h_end == h_trunc + 1 &&
- get_pht_entry_from_index(GC_dirty_pages, PHT_HASH(h_trunc))) {
+ get_pht_entry_from_index_async(GC_dirty_pages, PHT_HASH(h_trunc))) {
/* already marked dirty, and hence unprotected. */
return;
}