blob: 2a6d98022008c77798b7a83f7701e494dacc4e3d [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
// This header defines thread annotation macros to be used everywhere in Zircon
// outside of publicly exposed headers. See system/public/zircon/compiler.h for
// the publicly exported macros.
// The thread safety analysis system is documented at
// http://clang.llvm.org/docs/ThreadSafetyAnalysis.html and its use in Zircon is documented at
// docs/thread_annotations.md. The macros we use are:
//
// TA_CAP(x) |x| is the capability this type represents, e.g. "mutex".
// TA_GUARDED(x) the annotated variable is guarded by the capability (e.g. lock) |x|
// TA_ACQ(x) function acquires the mutex |x|
// TA_ACQ_SHARED(x) function acquires the mutex |x| for shared reading
// TA_ACQ_BEFORE(x) Indicates that if both this mutex and muxex |x| are to be acquired,
// that this mutex must be acquired before mutex |x|.
// TA_ACQ_AFTER(x) Indicates that if both this mutex and muxex |x| are to be acquired,
// that this mutex must be acquired after mutex |x|.
// TA_TRY_ACQ(bool, x) function acquires the mutex |x| if the function returns |bool|
// TA_REL(x) function releases the mutex |x|
// TA_REL_SHARED(x) function releases the shared for reading mutex |x|
// TA_ASSERT(x) function asserts that |x| is held
// TA_ASSERT_SHARED(x) function asserts that |x| is held for shared reading
// TA_REQ(x) function requires that the caller hold the mutex |x|
// TA_REQ_SHARED(x) function requires that the caller hold the mutex |x| for shared
// reading TA_EXCL(x) function requires that the caller not be holding the mutex
// |x| TA_RET_CAP(x) function returns a reference to the mutex |x| TA_SCOPED_CAP type
// represents a scoped or RAII-style wrapper around a capability TA_NO_THREAD_SAFETY_ANALYSIS
// function is excluded entirely from thread safety analysis
#ifdef __clang__
#define THREAD_ANNOTATION(x) __attribute__((x))
#else
#define THREAD_ANNOTATION(x)
#endif
#define TA_CAP(x) THREAD_ANNOTATION(capability(x))
#define TA_GUARDED(x) THREAD_ANNOTATION(guarded_by(x))
#define TA_ACQ(...) THREAD_ANNOTATION(acquire_capability(__VA_ARGS__))
#define TA_ACQ_SHARED(...) THREAD_ANNOTATION(acquire_shared_capability(__VA_ARGS__))
#define TA_ACQ_BEFORE(...) THREAD_ANNOTATION(acquired_before(__VA_ARGS__))
#define TA_ACQ_AFTER(...) THREAD_ANNOTATION(acquired_after(__VA_ARGS__))
#define TA_TRY_ACQ(...) THREAD_ANNOTATION(try_acquire_capability(__VA_ARGS__))
#define TA_REL(...) THREAD_ANNOTATION(release_capability(__VA_ARGS__))
#define TA_REL_SHARED(...) THREAD_ANNOTATION(release_shared_capability(__VA_ARGS__))
#define TA_ASSERT(...) THREAD_ANNOTATION(assert_capability(__VA_ARGS__))
#define TA_ASSERT_SHARED(...) THREAD_ANNOTATION(assert_shared_capability(__VA_ARGS__))
#define TA_REQ(...) THREAD_ANNOTATION(requires_capability(__VA_ARGS__))
#define TA_REQ_SHARED(...) THREAD_ANNOTATION(requires_shared_capability(__VA_ARGS__))
#define TA_EXCL(...) THREAD_ANNOTATION(locks_excluded(__VA_ARGS__))
#define TA_RET_CAP(x) THREAD_ANNOTATION(lock_returned(x))
#define TA_SCOPED_CAP THREAD_ANNOTATION(scoped_lockable)
#define TA_NO_THREAD_SAFETY_ANALYSIS THREAD_ANNOTATION(no_thread_safety_analysis)