summaryrefslogtreecommitdiff
path: root/perl.h
diff options
context:
space:
mode:
Diffstat (limited to 'perl.h')
-rw-r--r--perl.h116
1 files changed, 115 insertions, 1 deletions
diff --git a/perl.h b/perl.h
index c11548db22..cddae1519b 100644
--- a/perl.h
+++ b/perl.h
@@ -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