summaryrefslogtreecommitdiff
path: root/lib/tsan/rtl/tsan_libdispatch_mac.cc
diff options
context:
space:
mode:
authorKuba Mracek <mracek@apple.com>2017-03-26 20:59:23 +0000
committerKuba Mracek <mracek@apple.com>2017-03-26 20:59:23 +0000
commitea0ff516f0343d98f338c2403566f68a131b07e3 (patch)
tree2fd5fe111e09f14040f6ad3e64f7d2e799d40dc1 /lib/tsan/rtl/tsan_libdispatch_mac.cc
parent96ccf181c8c1bf446bae8fc738b3dc8da5a65cfe (diff)
[tsan] Only Acquire/Release GCD queues if they're not NULL
While it's usually a bug to call GCD APIs, such as dispatch_after, with NULL as a queue, this often "somehow" works and TSan should maintain binary compatibility with existing code. This patch makes sure we don't try to call Acquire and Release on NULL queues, and add one such testcase for dispatch_after. Differential Revision: https://reviews.llvm.org/D31355 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@298820 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/tsan/rtl/tsan_libdispatch_mac.cc')
-rw-r--r--lib/tsan/rtl/tsan_libdispatch_mac.cc17
1 files changed, 9 insertions, 8 deletions
diff --git a/lib/tsan/rtl/tsan_libdispatch_mac.cc b/lib/tsan/rtl/tsan_libdispatch_mac.cc
index 48351e80a..8c759a3be 100644
--- a/lib/tsan/rtl/tsan_libdispatch_mac.cc
+++ b/lib/tsan/rtl/tsan_libdispatch_mac.cc
@@ -97,11 +97,11 @@ static tsan_block_context_t *AllocContext(ThreadState *thr, uptr pc,
return new_context;
}
-#define GET_QUEUE_SYNC_VARS(context, q) \
- bool is_queue_serial = q && IsQueueSerial(q); \
- uptr sync_ptr = (uptr)q ?: context->non_queue_sync_object; \
- uptr serial_sync = (uptr)sync_ptr; \
- uptr concurrent_sync = ((uptr)sync_ptr) + sizeof(uptr); \
+#define GET_QUEUE_SYNC_VARS(context, q) \
+ bool is_queue_serial = q && IsQueueSerial(q); \
+ uptr sync_ptr = (uptr)q ?: context->non_queue_sync_object; \
+ uptr serial_sync = (uptr)sync_ptr; \
+ uptr concurrent_sync = sync_ptr ? ((uptr)sync_ptr) + sizeof(uptr) : 0; \
bool serial_task = context->is_barrier_block || is_queue_serial
static void dispatch_sync_pre_execute(ThreadState *thr, uptr pc,
@@ -112,8 +112,8 @@ static void dispatch_sync_pre_execute(ThreadState *thr, uptr pc,
dispatch_queue_t q = context->queue;
do {
GET_QUEUE_SYNC_VARS(context, q);
- Acquire(thr, pc, serial_sync);
- if (serial_task) Acquire(thr, pc, concurrent_sync);
+ if (serial_sync) Acquire(thr, pc, serial_sync);
+ if (serial_task && concurrent_sync) Acquire(thr, pc, concurrent_sync);
if (q) q = GetTargetQueueFromQueue(q);
} while (q);
@@ -127,7 +127,8 @@ static void dispatch_sync_post_execute(ThreadState *thr, uptr pc,
dispatch_queue_t q = context->queue;
do {
GET_QUEUE_SYNC_VARS(context, q);
- Release(thr, pc, serial_task ? serial_sync : concurrent_sync);
+ if (serial_task && serial_sync) Release(thr, pc, serial_sync);
+ if (!serial_task && concurrent_sync) Release(thr, pc, concurrent_sync);
if (q) q = GetTargetQueueFromQueue(q);
} while (q);