skia2/include/private/SkThreadAnnotations.h
Mike Klein a1991f5e3b experimental support for go/fibers
When run on cooperative threads, we need to notify the threading system
when we're going to block (in any way, sleep or spin) so that it doesn't
wake that thread up expecting it to make forward progress.

This should cover SkOnce, SkSpinlock, SkSemaphore, and by extension
SkMutex.  Not sure if there are others to hit, but really the only way
to find out is by deadlocked stack traces.  This CL (obviously?) does
nothing to mark synchronization primitives used by Skia's dependencies,
and in general I don't think we can do anything about them.

See cr/275261423 for more background and discussion.  It's not clear to
me that marking these symbols as weak is necessary, so I figured I'd
just try not doing that and seeing what breaks.  I can always follow up
with weak symbols if proven necessary.

Bug: skia:9577

Change-Id: I2c03fe92c58ad506dd8a68bdc90a09b28f965149
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/251221
Commit-Queue: Mike Klein <mtklein@google.com>
Auto-Submit: Mike Klein <mtklein@google.com>
Reviewed-by: Herb Derby <herb@google.com>
2019-10-28 16:48:55 +00:00

92 lines
2.9 KiB
C

/*
* Copyright 2019 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkThreadAnnotations_DEFINED
#define SkThreadAnnotations_DEFINED
// The bulk of this code is cribbed from:
// http://clang.llvm.org/docs/ThreadSafetyAnalysis.html
#if defined(__clang__) && (!defined(SWIG))
#define SK_THREAD_ANNOTATION_ATTRIBUTE(x) __attribute__((x))
#else
#define SK_THREAD_ANNOTATION_ATTRIBUTE(x) // no-op
#endif
#define SK_CAPABILITY(x) \
SK_THREAD_ANNOTATION_ATTRIBUTE(capability(x))
#define SK_SCOPED_CAPABILITY \
SK_THREAD_ANNOTATION_ATTRIBUTE(scoped_lockable)
#define SK_GUARDED_BY(x) \
SK_THREAD_ANNOTATION_ATTRIBUTE(guarded_by(x))
#define SK_PT_GUARDED_BY(x) \
SK_THREAD_ANNOTATION_ATTRIBUTE(pt_guarded_by(x))
#define SK_ACQUIRED_BEFORE(...) \
SK_THREAD_ANNOTATION_ATTRIBUTE(acquired_before(__VA_ARGS__))
#define SK_ACQUIRED_AFTER(...) \
SK_THREAD_ANNOTATION_ATTRIBUTE(acquired_after(__VA_ARGS__))
#define SK_REQUIRES(...) \
SK_THREAD_ANNOTATION_ATTRIBUTE(requires_capability(__VA_ARGS__))
#define SK_REQUIRES_SHARED(...) \
SK_THREAD_ANNOTATION_ATTRIBUTE(requires_shared_capability(__VA_ARGS__))
#define SK_ACQUIRE(...) \
SK_THREAD_ANNOTATION_ATTRIBUTE(acquire_capability(__VA_ARGS__))
#define SK_ACQUIRE_SHARED(...) \
SK_THREAD_ANNOTATION_ATTRIBUTE(acquire_shared_capability(__VA_ARGS__))
// Would be SK_RELEASE, but that is already in use by SkPostConfig.
#define SK_RELEASE_CAPABILITY(...) \
SK_THREAD_ANNOTATION_ATTRIBUTE(release_capability(__VA_ARGS__))
// For symmetry with SK_RELEASE_CAPABILITY.
#define SK_RELEASE_SHARED_CAPABILITY(...) \
SK_THREAD_ANNOTATION_ATTRIBUTE(release_shared_capability(__VA_ARGS__))
#define SK_TRY_ACQUIRE(...) \
SK_THREAD_ANNOTATION_ATTRIBUTE(try_acquire_capability(__VA_ARGS__))
#define SK_TRY_ACQUIRE_SHARED(...) \
SK_THREAD_ANNOTATION_ATTRIBUTE(try_acquire_shared_capability(__VA_ARGS__))
#define SK_EXCLUDES(...) \
SK_THREAD_ANNOTATION_ATTRIBUTE(locks_excluded(__VA_ARGS__))
#define SK_ASSERT_CAPABILITY(x) \
SK_THREAD_ANNOTATION_ATTRIBUTE(assert_capability(x))
#define SK_ASSERT_SHARED_CAPABILITY(x) \
SK_THREAD_ANNOTATION_ATTRIBUTE(assert_shared_capability(x))
#define SK_RETURN_CAPABILITY(x) \
SK_THREAD_ANNOTATION_ATTRIBUTE(lock_returned(x))
#define SK_NO_THREAD_SAFETY_ANALYSIS \
SK_THREAD_ANNOTATION_ATTRIBUTE(no_thread_safety_analysis)
#if defined(SK_BUILD_FOR_GOOGLE3)
extern "C" {
void __google_potentially_blocking_region_begin(void);
void __google_potentially_blocking_region_end (void);
}
#define SK_POTENTIALLY_BLOCKING_REGION_BEGIN __google_potentially_blocking_region_begin()
#define SK_POTENTIALLY_BLOCKING_REGION_END __google_potentially_blocking_region_end()
#else
#define SK_POTENTIALLY_BLOCKING_REGION_BEGIN
#define SK_POTENTIALLY_BLOCKING_REGION_END
#endif
#endif // SkThreadAnnotations_DEFINED