Skip to content

Commit

Permalink
Add tsan macro to detect all races on const/non-const thread compatib…
Browse files Browse the repository at this point in the history
…le upb arena functions

PiperOrigin-RevId: 718027753
  • Loading branch information
protobuf-github-bot authored and copybara-github committed Jan 21, 2025
1 parent 7eec7a0 commit 8e6b727
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 0 deletions.
2 changes: 2 additions & 0 deletions upb/mem/arena.c
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,7 @@ static void _upb_Arena_DoFuseArenaLists(upb_ArenaInternal* const parent,
}

void upb_Arena_SetAllocCleanup(upb_Arena* a, upb_AllocCleanupFunc* func) {
UPB_TSAN_CHECK_READ(a->UPB_ONLYBITS(ptr));
upb_ArenaInternal* ai = upb_Arena_Internal(a);
UPB_ASSERT(ai->upb_alloc_cleanup == NULL);
ai->upb_alloc_cleanup = func;
Expand Down Expand Up @@ -701,6 +702,7 @@ void upb_Arena_DecRefFor(const upb_Arena* a, const void* owner) {
}

upb_alloc* upb_Arena_GetUpbAlloc(upb_Arena* a) {
UPB_TSAN_CHECK_READ(a->UPB_ONLYBITS(ptr));
upb_ArenaInternal* ai = upb_Arena_Internal(a);
return _upb_ArenaInternal_BlockAlloc(ai);
}
Expand Down
3 changes: 3 additions & 0 deletions upb/mem/internal/arena.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ UPB_INLINE size_t UPB_PRIVATE(_upb_ArenaHas)(const struct upb_Arena* a) {
}

UPB_API_INLINE void* upb_Arena_Malloc(struct upb_Arena* a, size_t size) {
UPB_TSAN_CHECK_WRITE(a->UPB_ONLYBITS(ptr));
void* UPB_PRIVATE(_upb_Arena_SlowMalloc)(struct upb_Arena * a, size_t size);

size = UPB_ALIGN_MALLOC(size);
Expand All @@ -66,6 +67,7 @@ UPB_API_INLINE void* upb_Arena_Malloc(struct upb_Arena* a, size_t size) {

UPB_API_INLINE void* upb_Arena_Realloc(struct upb_Arena* a, void* ptr,
size_t oldsize, size_t size) {
UPB_TSAN_CHECK_WRITE(a->UPB_ONLYBITS(ptr));
oldsize = UPB_ALIGN_MALLOC(oldsize);
size = UPB_ALIGN_MALLOC(size);
bool is_most_recent_alloc =
Expand All @@ -92,6 +94,7 @@ UPB_API_INLINE void* upb_Arena_Realloc(struct upb_Arena* a, void* ptr,

UPB_API_INLINE void upb_Arena_ShrinkLast(struct upb_Arena* a, void* ptr,
size_t oldsize, size_t size) {
UPB_TSAN_CHECK_WRITE(a->UPB_ONLYBITS(ptr));
oldsize = UPB_ALIGN_MALLOC(oldsize);
size = UPB_ALIGN_MALLOC(size);
// Must be the last alloc.
Expand Down
14 changes: 14 additions & 0 deletions upb/port/def.inc
Original file line number Diff line number Diff line change
Expand Up @@ -374,13 +374,27 @@ void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
#define UPB_TSAN_CHECK_PUBLISHED(ptr) \
UPB_ASSERT((ptr)->upb_tsan_safely_published == 0x5AFE)
#define UPB_TSAN_PUBLISH 1
#define UPB_TSAN_CHECK_READ(member) asm volatile("" ::"r"(*(char *)&(member)))
#define UPB_TSAN_CHECK_WRITE(member) \
do { \
char *write_upb_tsan_detect_race_ptr = (char *)&(member); \
char write_upb_tsan_detect_race = *write_upb_tsan_detect_race_ptr; \
asm volatile("" : "+r"(write_upb_tsan_detect_race)); \
*write_upb_tsan_detect_race_ptr = write_upb_tsan_detect_race; \
} while (false)
#else
#define UPB_TSAN_PUBLISHED_MEMBER
#define UPB_TSAN_INIT_PUBLISHED(ptr)
#define UPB_TSAN_CHECK_PUBLISHED(ptr) \
do { \
} while (false && (ptr))
#define UPB_TSAN_PUBLISH 0
#define UPB_TSAN_CHECK_READ(member) \
do { \
} while (false && (member))
#define UPB_TSAN_CHECK_WRITE(member) \
do { \
} while (false && (member))
#endif

/* Disable proto2 arena behavior (TEMPORARY) **********************************/
Expand Down
2 changes: 2 additions & 0 deletions upb/port/undef.inc
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
#undef UPB_TSAN_INIT_PUBLISHED
#undef UPB_TSAN_CHECK_PUBLISHED
#undef UPB_TSAN_PUBLISH
#undef UPB_TSAN_CHECK_READ
#undef UPB_TSAN_CHECK_WRITE
#undef UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN
#undef UPB_DEPRECATED
#undef UPB_GNUC_MIN
Expand Down

0 comments on commit 8e6b727

Please sign in to comment.