Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[core] Added Clang TSA attributes. #2000

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ option(USE_BUSY_WAITING "Enable more accurate sending times at a cost of potenti
option(USE_GNUSTL "Get c++ library/headers from the gnustl.pc" OFF)
option(ENABLE_SOCK_CLOEXEC "Enable setting SOCK_CLOEXEC on a socket" ON)

option(ENABLE_CLANG_TSA "Enable Clang Thread Safety Analysis" OFF)

set(TARGET_srt "srt" CACHE STRING "The name for the SRT library")

# Use application-defined group reader
Expand Down Expand Up @@ -634,6 +636,11 @@ if (ENABLE_THREAD_CHECK)
)
endif()

if (ENABLE_CLANG_TSA)
list(APPEND SRT_EXTRA_CFLAGS "-Wthread-safety")
message(STATUS "Clang TSA: Enabled")
endif()

if (ENABLE_PROFILE)
if (HAVE_COMPILER_GNU_COMPAT)
# They are actually cflags, not definitions, but CMake is stupid enough.
Expand Down
3 changes: 3 additions & 0 deletions srtcore/logging.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,10 @@ struct LogConfig
{
}

SRT_ATTR_ACQUIRE(mutex)
void lock() { mutex.lock(); }

SRT_ATTR_RELEASE(mutex)
void unlock() { mutex.unlock(); }
};

Expand Down
2 changes: 1 addition & 1 deletion srtcore/platform_sys.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
#include <stdint.h>
#include <inttypes.h>
#if defined(_MSC_VER)
#pragma warning(disable:4251)
#pragma warning(disable: 4251 26812)
#endif
#else

Expand Down
2 changes: 1 addition & 1 deletion srtcore/srt.h
Original file line number Diff line number Diff line change
Expand Up @@ -961,7 +961,7 @@ typedef struct SRT_EPOLL_EVENT_STR
int events; // SRT_EPOLL_IN | SRT_EPOLL_OUT | SRT_EPOLL_ERR
#ifdef __cplusplus
SRT_EPOLL_EVENT_STR(SRTSOCKET s, int ev): fd(s), events(ev) {}
SRT_EPOLL_EVENT_STR() {} // NOTE: allows singular values, no init.
SRT_EPOLL_EVENT_STR(): fd(-1), events(0) {} // NOTE: allows singular values, no init.
#endif
} SRT_EPOLL_EVENT;
SRT_API int srt_epoll_uwait(int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut);
Expand Down
119 changes: 119 additions & 0 deletions srtcore/srt_attr_defs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* SRT - Secure, Reliable, Transport
* Copyright (c) 2019 Haivision Systems Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
/*****************************************************************************
The file contains various planform and compiler dependent attribute definitions
used by SRT library internally.

1. Attributes for thread safety analysis
- Clang (https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutexheader).
- Other compilers: none.

*****************************************************************************/

#ifndef INC_SRT_ATTR_DEFS_H
#define INC_SRT_ATTR_DEFS_H

#if _MSC_VER >= 1920
// In case of MSVC these attributes have to preceed the attributed objects (variable, function).
// E.g. SRT_ATTR_GUARDED_BY(mtx) int object;
// It is tricky to annotate e.g. the following function, as clang complaints it does not know 'm'.
// SRT_ATTR_EXCLUDES(m) SRT_ATTR_ACQUIRE(m)
// inline void enterCS(Mutex& m) { m.lock(); }
#define SRT_ATTR_CAPABILITY(expr)
#define SRT_ATTR_SCOPED_CAPABILITY
#define SRT_ATTR_GUARDED_BY(expr) _Guarded_by_(expr)
#define SRT_ATTR_PT_GUARDED_BY(expr)
#define SRT_ATTR_ACQUIRED_BEFORE(...)
#define SRT_ATTR_ACQUIRED_AFTER(...)
#define SRT_ATTR_REQUIRES(expr) _Requires_lock_held_(expr)
#define SRT_ATTR_REQUIRES_SHARED(...)
#define SRT_ATTR_ACQUIRE(expr) _Acquires_nonreentrant_lock_(expr)
#define SRT_ATTR_ACQUIRE_SHARED(...)
#define SRT_ATTR_RELEASE(expr) _Releases_lock_(expr)
#define SRT_ATTR_RELEASE_SHARED(...)
#define SRT_ATTR_RELEASE_GENERIC(...)
#define SRT_ATTR_TRY_ACQUIRE(...) _Acquires_nonreentrant_lock_(expr)
#define SRT_ATTR_TRY_ACQUIRE_SHARED(...)
#define SRT_ATTR_EXCLUDES(...)
#define SRT_ATTR_ASSERT_CAPABILITY(expr)
#define SRT_ATTR_ASSERT_SHARED_CAPABILITY(x)
#define SRT_ATTR_RETURN_CAPABILITY(x)
#define SRT_ATTR_NO_THREAD_SAFETY_ANALYSIS
#else

#if defined(__clang__)
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
#else
#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
#endif

#define SRT_ATTR_CAPABILITY(x) \
THREAD_ANNOTATION_ATTRIBUTE__(capability(x))

#define SRT_ATTR_SCOPED_CAPABILITY \
THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)

#define SRT_ATTR_GUARDED_BY(x) \
THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))

#define SRT_ATTR_PT_GUARDED_BY(x) \
THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))

#define SRT_ATTR_ACQUIRED_BEFORE(...) \
THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))

#define SRT_ATTR_ACQUIRED_AFTER(...) \
THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))

#define SRT_ATTR_REQUIRES(...) \
THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__))

#define SRT_ATTR_REQUIRES_SHARED(...) \
THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__))

#define SRT_ATTR_ACQUIRE(...) \
THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__))

#define SRT_ATTR_ACQUIRE_SHARED(...) \
THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__))

#define SRT_ATTR_RELEASE(...) \
THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__))

#define SRT_ATTR_RELEASE_SHARED(...) \
THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__))

#define SRT_ATTR_RELEASE_GENERIC(...) \
THREAD_ANNOTATION_ATTRIBUTE__(release_generic_capability(__VA_ARGS__))

#define SRT_ATTR_TRY_ACQUIRE(...) \
THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__))

#define SRT_ATTR_TRY_ACQUIRE_SHARED(...) \
THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__))

#define SRT_ATTR_EXCLUDES(...) \
THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))

#define SRT_ATTR_ASSERT_CAPABILITY(x) \
THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x))

#define SRT_ATTR_ASSERT_SHARED_CAPABILITY(x) \
THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x))

#define SRT_ATTR_RETURN_CAPABILITY(x) \
THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))

#define SRT_ATTR_NO_THREAD_SAFETY_ANALYSIS \
THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)

#endif // not _MSC_VER

#endif // INC_SRT_ATTR_DEFS_H
46 changes: 30 additions & 16 deletions srtcore/sync.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#endif // ENABLE_STDCXX_SYNC

#include "utilities.h"
#include "srt_attr_defs.h"

class CUDTException; // defined in common.h

Expand Down Expand Up @@ -304,7 +305,7 @@ using ScopedLock = lock_guard<mutex>;
/// Mutex is a class wrapper, that should mimic the std::chrono::mutex class.
/// At the moment the extra function ref() is temporally added to allow calls
/// to pthread_cond_timedwait(). Will be removed by introducing CEvent.
class Mutex
class SRT_ATTR_CAPABILITY("mutex") Mutex
{
friend class SyncEvent;

Expand All @@ -313,11 +314,11 @@ class Mutex
~Mutex();

public:
int lock();
int unlock();
int lock() SRT_ATTR_ACQUIRE();
int unlock() SRT_ATTR_RELEASE();

/// @return true if the lock was acquired successfully, otherwise false
bool try_lock();
bool try_lock() SRT_ATTR_TRY_ACQUIRE(true);

// TODO: To be removed with introduction of the CEvent.
pthread_mutex_t& ref() { return m_mutex; }
Expand All @@ -327,28 +328,39 @@ class Mutex
};

/// A pthread version of std::chrono::scoped_lock<mutex> (or lock_guard for C++11)
class ScopedLock
class SRT_ATTR_SCOPED_CAPABILITY ScopedLock
{
public:
SRT_ATTR_ACQUIRE(m)
ScopedLock(Mutex& m);

SRT_ATTR_RELEASE()
~ScopedLock();

private:
Mutex& m_mutex;
};

/// A pthread version of std::chrono::unique_lock<mutex>
class UniqueLock
class SRT_ATTR_SCOPED_CAPABILITY UniqueLock
{
friend class SyncEvent;

public:
SRT_ATTR_ACQUIRE(m_Mutex)
UniqueLock(Mutex &m);

SRT_ATTR_RELEASE(m_Mutex)
~UniqueLock();

public:
SRT_ATTR_ACQUIRE(m_Mutex)
void lock();

SRT_ATTR_RELEASE(m_Mutex)
void unlock();

SRT_ATTR_RETURN_CAPABILITY(m_Mutex)
Mutex* mutex(); // reflects C++11 unique_lock::mutex()

private:
Expand All @@ -357,26 +369,28 @@ class UniqueLock
};
#endif // ENABLE_STDCXX_SYNC

inline void enterCS(Mutex& m) { m.lock(); }
inline bool tryEnterCS(Mutex& m) { return m.try_lock(); }
inline void leaveCS(Mutex& m) { m.unlock(); }
inline void enterCS(Mutex& m) SRT_ATTR_EXCLUDES(m) SRT_ATTR_ACQUIRE(m) { m.lock(); }

inline bool tryEnterCS(Mutex& m) SRT_ATTR_TRY_ACQUIRE(true, m) { return m.try_lock(); }

inline void leaveCS(Mutex& m) SRT_ATTR_REQUIRES(m) SRT_ATTR_RELEASE(m) { m.unlock(); }

class InvertedLock
{
Mutex *m_pMutex;
Mutex& m_mtx;

public:
public:
SRT_ATTR_REQUIRES(m) SRT_ATTR_RELEASE(m)
InvertedLock(Mutex& m)
: m_pMutex(&m)
: m_mtx(m)
{
leaveCS(*m_pMutex);
m_mtx.unlock();
}

SRT_ATTR_ACQUIRE(m_mtx)
~InvertedLock()
{
if (!m_pMutex)
return;
enterCS(*m_pMutex);
m_mtx.lock();
}
};

Expand Down
21 changes: 13 additions & 8 deletions srtcore/sync_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,22 +244,27 @@ srt::sync::UniqueLock::UniqueLock(Mutex& m)

srt::sync::UniqueLock::~UniqueLock()
{
unlock();
if (m_iLocked == 0)
{
unlock();
}
}

void srt::sync::UniqueLock::lock()
{
if (m_iLocked == -1)
m_iLocked = m_Mutex.lock();
if (m_iLocked != -1)
throw CThreadException(MJ_SYSTEMRES, MN_THREAD, 0);

m_iLocked = m_Mutex.lock();
}

void srt::sync::UniqueLock::unlock()
{
if (m_iLocked == 0)
{
m_Mutex.unlock();
m_iLocked = -1;
}
if (m_iLocked != 0)
throw CThreadException(MJ_SYSTEMRES, MN_THREAD, 0);

m_Mutex.unlock();
m_iLocked = -1;
}

srt::sync::Mutex* srt::sync::UniqueLock::mutex()
Expand Down
4 changes: 2 additions & 2 deletions srtcore/udt.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ modified by
#include "srt.h"

/*
* SRT_ENABLE_THREADCHECK (THIS IS SET IN MAKEFILE NOT HERE)
* SRT_ENABLE_THREADCHECK IS SET IN MAKEFILE, NOT HERE
*/
#if defined(SRT_ENABLE_THREADCHECK)
#include <threadcheck.h>
#include "threadcheck.h"
#else
#define THREAD_STATE_INIT(name)
#define THREAD_EXIT()
Expand Down