diff options
Diffstat (limited to 'perl.h')
-rw-r--r-- | perl.h | 116 |
1 files changed, 115 insertions, 1 deletions
@@ -3052,6 +3052,101 @@ freeing any remaining Perl interpreters. * May make sense to have threads after "*ish.h" anyway */ +/* clang Thread Safety Analysis/Annotations/Attributes + * http://clang.llvm.org/docs/ThreadSafetyAnalysis.html + * + * Available since clang 3.5-ish (appeared in 3.4, but shaky). + * Apple XCode hijacks __clang_major__ and __clang_minor__ + * (6.0 means really clang 3.5), so needs extra hijinks. + */ +#if defined(USE_ITHREADS) && defined(I_PTHREAD) && \ + defined(__clang__) && \ + !defined(SWIG) && \ + ((!defined(__apple_build_version__) && \ + ((__clang_major__ == 3 && __clang_minor__ >= 5) || \ + (__clang_major__ > 4))) || \ + (defined(__apple_build_version__) && \ + ((__clang_major__ >= 6)))) +# define PERL_TSA__(x) __attribute__((x)) +# define PERL_TSA_ACTIVE +#else +# define PERL_TSA__(x) /* No TSA, make TSA attributes no-ops. */ +# undef PERL_TSA_ACTIVE +#endif + +/* PERL_TSA_CAPABILITY() is used to annotate typedefs. + * typedef old_type PERL_TSA_CAPABILITY("mutex") new_type; + */ +#define PERL_TSA_CAPABILITY(x) \ + PERL_TSA__(capability(x)) + +/* In the below examples the mutex must be lexically visible, usually + * either as global variables, or as function arguments. */ + +/* PERL_TSA_GUARDED_BY() is used to annotate global variables. + * + * Foo foo PERL_TSA_GUARDED_BY(mutex); + */ +#define PERL_TSA_GUARDED_BY(x) \ + PERL_TSA__(guarded_by(x)) + +/* PERL_TSA_PT_GUARDED_BY() is used to annotate global pointers. + * The data _behind_ the pointer is guarded. + * + * Foo* ptr PERL_TSA_PT_GUARDED_BY(mutex); + */ +#define PERL_TSA_PT_GUARDED_BY(x) \ + PERL_TSA__(pt_guarded_by(x)) + +/* PERL_TSA_REQUIRES() is used to annotate functions. + * The caller MUST hold the resource when calling the function. + * + * void Foo() PERL_TSA_REQUIRES(mutex); + */ +#define PERL_TSA_REQUIRES(x) \ + PERL_TSA__(requires_capability(x)) + +/* PERL_TSA_EXCLUDES() is used to annotate functions. + * The caller MUST NOT hold resource when calling the function. + * + * EXCLUDES should be used when the function first acquires + * the resource and then releases it. Use to avoid deadlock. + * + * void Foo() PERL_TSA_EXCLUDES(mutex); + */ +#define PERL_TSA_EXCLUDES(x) \ + PERL_TSA__(locks_excluded(x)) + +/* PERL_TSA_ACQUIRE() is used to annotate functions. + * The caller MUST NOT hold the resource when calling the function, + * and the function will acquire the resource. + * + * void Foo() PERL_TSA_ACQUIRE(mutex); + */ +#define PERL_TSA_ACQUIRE(x) \ + PERL_TSA__(acquire_capability(x)) + +/* PERL_TSA_RELEASE() is used to annotate functions. + * The caller MUST hold the resource when calling the function, + * and the function will release the resource. + * + * void Foo() PERL_TSA_RELEASE(mutex); + */ +#define PERL_TSA_RELEASE(x) \ + PERL_TSA__(release_capability(x)) + +/* PERL_TSA_NO_TSA is used to annotate functions. + * Used when being intentionally unsafe, or when the code is too + * complicated for the analysis. Use sparingly. + * + * void Foo() PERL_TSA_NO_TSA; + */ +#define PERL_TSA_NO_TSA \ + PERL_TSA__(no_thread_safety_analysis) + +/* There are more annotations/attributes available, see the clang + * documentation for details. */ + #if defined(USE_ITHREADS) # ifdef NETWARE # include <nw5thread.h> @@ -3073,7 +3168,7 @@ typedef void * perl_key; # include <pthread.h> # endif typedef pthread_t perl_os_thread; -typedef pthread_mutex_t perl_mutex; +typedef pthread_mutex_t PERL_TSA_CAPABILITY("mutex") perl_mutex; typedef pthread_cond_t perl_cond; typedef pthread_key_t perl_key; # endif /* I_MACH_CTHREADS */ @@ -3082,6 +3177,25 @@ typedef pthread_key_t perl_key; # endif /* NETWARE */ #endif /* USE_ITHREADS */ +#ifdef PERL_TSA_ACTIVE +/* Since most pthread mutex interfaces have not been annotated, we + * need to have these wrappers. The NO_TSA annotation is quite ugly + * but it cannot be avoided in plain C, unlike in C++, where one could + * e.g. use ACQUIRE() with no arg on a mutex lock method. + * + * The bodies of these wrappers are in util.c + * + * TODO: however, some platforms are starting to get these clang + * thread safety annotations for pthreads, for example FreeBSD. + * Do we need a way to a bypass these wrappers? */ +int perl_tsa_mutex_lock(perl_mutex* mutex) + PERL_TSA_ACQUIRE(*mutex) + PERL_TSA_NO_TSA; +int perl_tsa_mutex_unlock(perl_mutex* mutex) + PERL_TSA_RELEASE(*mutex) + PERL_TSA_NO_TSA; +#endif + #if defined(WIN32) # include "win32.h" #endif |