X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/53e89cff0d987b819572bfbbb8759a2f402dacbe..d15ad02e8936a558368fd0a2b425c0e184ee848e:/perl.h diff --git a/perl.h b/perl.h index b040291..960a8a5 100644 --- a/perl.h +++ b/perl.h @@ -35,7 +35,7 @@ * NOTE 2: headers lie. Do not expect that if HAS_C99 gets to be true, * all the C99 features are there and are correct. */ #if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ - defined(_STDC_C99) + defined(_STDC_C99) || defined(__c99) # define HAS_C99 1 #endif @@ -421,6 +421,16 @@ # define GCC_DIAG_IGNORE(w) # define GCC_DIAG_RESTORE #endif +/* for clang specific pragmas */ +#if defined(__clang__) || defined(__clang) +# define CLANG_DIAG_PRAGMA(x) _Pragma (#x) +# define CLANG_DIAG_IGNORE(x) _Pragma("clang diagnostic push") \ + CLANG_DIAG_PRAGMA(clang diagnostic ignored #x) +# define CLANG_DIAG_RESTORE _Pragma("clang diagnostic pop") +#else +# define CLANG_DIAG_IGNORE(w) +# define CLANG_DIAG_RESTORE +#endif #define NOOP /*EMPTY*/(void)0 /* cea2e8a9dd23747f accidentally lost the comment originally from the first @@ -597,9 +607,9 @@ # define TAINT_WARN_get 0 # define TAINT_WARN_set(s) NOOP #else -# define TAINT (PL_tainted = TRUE) +# define TAINT (PL_tainted = PL_tainting) # define TAINT_NOT (PL_tainted = FALSE) -# define TAINT_IF(c) if (UNLIKELY(c)) { PL_tainted = TRUE; } +# define TAINT_IF(c) if (UNLIKELY(c)) { PL_tainted = PL_tainting; } # define TAINT_ENV() if (UNLIKELY(PL_tainting)) { taint_env(); } # define TAINT_PROPER(s) if (UNLIKELY(PL_tainting)) { taint_proper(NULL, s); } # define TAINT_set(s) (PL_tainted = (s)) @@ -1868,6 +1878,9 @@ typedef NVTYPE NV; /* Also Tru64 cc has broken NaN comparisons. */ # define NAN_COMPARE_BROKEN #endif +#if defined(__sgi) +# define NAN_COMPARE_BROKEN +#endif #ifdef USE_LONG_DOUBLE # ifdef I_SUNMATH @@ -1965,11 +1978,15 @@ extern long double Perl_my_frexpl(long double x, int *e); # ifndef Perl_isnan # if defined(HAS_ISNANL) && !(defined(isnan) && defined(HAS_C99)) # define Perl_isnan(x) isnanl(x) +# elif defined(__sgi) && defined(__c99) /* XXX Configure test needed */ +# define Perl_isnan(x) isnan(x) # endif # endif # ifndef Perl_isinf # if defined(HAS_ISINFL) && !(defined(isinf) && defined(HAS_C99)) # define Perl_isinf(x) isinfl(x) +# elif defined(__sgi) && defined(__c99) /* XXX Configure test needed */ +# define Perl_isinf(x) isinf(x) # elif defined(LDBL_MAX) && !defined(NAN_COMPARE_BROKEN) # define Perl_isinf(x) ((x) > LDBL_MAX || (x) < -LDBL_MAX) # endif @@ -2157,7 +2174,7 @@ extern long double Perl_my_frexpl(long double x, int *e); /* Solaris and IRIX have fpclass/fpclassl, but they are using * an enum typedef, not cpp symbols, and Configure doesn't detect that. * Define some symbols also as cpp symbols so we can detect them. */ -# if defined(__sun) || defined(__irix__) /* XXX Configure test instead */ +# if defined(__sun) || defined(__sgi) /* XXX Configure test instead */ # define FP_PINF FP_PINF # define FP_QNAN FP_QNAN # endif @@ -2207,7 +2224,7 @@ extern long double Perl_my_frexpl(long double x, int *e); # include # endif # if defined(FP_POS_INF) && defined(FP_QNAN) -# ifdef __irix__ /* XXX Configure test instead */ +# ifdef __sgi /* XXX Configure test instead */ # ifdef USE_LONG_DOUBLE # define Perl_fp_class(x) fp_class_l(x) # else @@ -2803,7 +2820,7 @@ typedef struct padname PADNAME; # include "unixish.h" #endif -#if defined(__amigaos4__) +#ifdef __amigaos4__ # include "amigaos.h" # undef FD_CLOEXEC /* a lie in AmigaOS */ #endif @@ -3045,6 +3062,103 @@ 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.6-ish (appeared in 3.4, but shaky still in 3.5). + * Apple XCode hijacks __clang_major__ and __clang_minor__ + * (6.1 means really clang 3.6), so needs extra hijinks + * (could probably also test the contents of __apple_build_version__). + */ +#if defined(USE_ITHREADS) && defined(I_PTHREAD) && \ + defined(__clang__) && \ + !defined(SWIG) && \ + ((!defined(__apple_build_version__) && \ + ((__clang_major__ == 3 && __clang_minor__ >= 6) || \ + (__clang_major__ >= 4))) || \ + (defined(__apple_build_version__) && \ + ((__clang_major__ == 6 && __clang_minor__ >= 1) || \ + (__clang_major__ >= 7)))) +# 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 @@ -3066,7 +3180,7 @@ typedef void * perl_key; # include # 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 */ @@ -3075,6 +3189,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 @@ -3269,6 +3402,32 @@ typedef pthread_key_t perl_key; vaxc$errno = PL_statusvalue_vms = MY_POSIX_EXIT ? \ (C_FAC_POSIX | (1 << 3) | STS$K_ERROR | STS$M_INHIB_MSG) : SS$_ABORT) +#elif defined(__amigaos4__) + /* A somewhat experimental attempt to simulate posix return code values */ +# define STATUS_NATIVE PL_statusvalue_posix +# define STATUS_NATIVE_CHILD_SET(n) \ + STMT_START { \ + PL_statusvalue_posix = (n); \ + if (PL_statusvalue_posix < 0) { \ + PL_statusvalue = -1; \ + } \ + else { \ + PL_statusvalue = n << 8; \ + } \ + } STMT_END +# define STATUS_UNIX_SET(n) \ + STMT_START { \ + PL_statusvalue = (n); \ + if (PL_statusvalue != -1) \ + PL_statusvalue &= 0xFFFF; \ + } STMT_END +# define STATUS_UNIX_EXIT_SET(n) STATUS_UNIX_SET(n) +# define STATUS_EXIT_SET(n) STATUS_UNIX_SET(n) +# define STATUS_CURRENT STATUS_UNIX +# define STATUS_EXIT STATUS_UNIX +# define STATUS_ALL_SUCCESS (PL_statusvalue = 0, PL_statusvalue_posix = 0) +# define STATUS_ALL_FAILURE (PL_statusvalue = 1, PL_statusvalue_posix = 1) + #else # define STATUS_NATIVE PL_statusvalue_posix # if defined(WCOREDUMP) @@ -4055,6 +4214,7 @@ Gid_t getegid (void); # define DEBUG_Xv_TEST_ (DEBUG_X_TEST_ && DEBUG_v_TEST_) # define DEBUG_Uv_TEST_ (DEBUG_U_TEST_ && DEBUG_v_TEST_) # define DEBUG_Pv_TEST_ (DEBUG_P_TEST_ && DEBUG_v_TEST_) +# define DEBUG_Lv_TEST_ (DEBUG_L_TEST_ && DEBUG_v_TEST_) #ifdef DEBUGGING @@ -4088,6 +4248,7 @@ Gid_t getegid (void); # define DEBUG_Xv_TEST DEBUG_Xv_TEST_ # define DEBUG_Uv_TEST DEBUG_Uv_TEST_ # define DEBUG_Pv_TEST DEBUG_Pv_TEST_ +# define DEBUG_Lv_TEST DEBUG_Lv_TEST_ # define PERL_DEB(a) a # define PERL_DEB2(a,b) a @@ -4127,6 +4288,7 @@ Gid_t getegid (void); # define DEBUG_Xv(a) DEBUG__(DEBUG_Xv_TEST, a) # define DEBUG_Uv(a) DEBUG__(DEBUG_Uv_TEST, a) # define DEBUG_Pv(a) DEBUG__(DEBUG_Pv_TEST, a) +# define DEBUG_Lv(a) DEBUG__(DEBUG_Lv_TEST, a) # define DEBUG_S(a) DEBUG__(DEBUG_S_TEST, a) # define DEBUG_T(a) DEBUG__(DEBUG_T_TEST, a) @@ -4171,6 +4333,7 @@ Gid_t getegid (void); # define DEBUG_Xv_TEST (0) # define DEBUG_Uv_TEST (0) # define DEBUG_Pv_TEST (0) +# define DEBUG_Lv_TEST (0) # define PERL_DEB(a) # define PERL_DEB2(a,b) b @@ -4204,6 +4367,7 @@ Gid_t getegid (void); # define DEBUG_Xv(a) # define DEBUG_Uv(a) # define DEBUG_Pv(a) +# define DEBUG_Lv(a) #endif /* DEBUGGING */ @@ -5413,20 +5577,6 @@ struct tempsym; /* defined in pp_pack.c */ # include "win32iop.h" #endif -/* DO_EXEC_TYPE is the return type of the do_*exec*() functions. - * For UNIXish platforms where the exec functions by definition - * return only failure, it can be bool (for success, they do not - * return). For other platforms, where the calling entity may - * return, the return value may be more complex. */ -#if defined(__amigaos4__) -# define DO_EXEC_TYPE I32 -# define DO_EXEC_FAILURE -1 -# define DO_EXEC_RETVAL(val) (val) -#else -# define DO_EXEC_TYPE bool -# define DO_EXEC_FAILURE FALSE -# define DO_EXEC_RETVAL(val) FALSE -#endif #include "proto.h" @@ -6468,14 +6618,6 @@ extern void moncontrol(int); /* See http://www.unicode.org/unicode/reports/tr13/ */ #define NEXT_LINE_CHAR NEXT_LINE_NATIVE -/* The UTF-8 bytes of the Unicode LS and PS, U+2028 and U+2029 */ -#define UNICODE_LINE_SEPA_0 0xE2 -#define UNICODE_LINE_SEPA_1 0x80 -#define UNICODE_LINE_SEPA_2 0xA8 -#define UNICODE_PARA_SEPA_0 0xE2 -#define UNICODE_PARA_SEPA_1 0x80 -#define UNICODE_PARA_SEPA_2 0xA9 - #ifndef PIPESOCK_MODE # define PIPESOCK_MODE #endif @@ -6616,16 +6758,21 @@ extern void moncontrol(int); # if LONG_DOUBLEKIND == LONG_DOUBLE_IS_IEEE_754_128_BIT_LITTLE_ENDIAN || \ LONG_DOUBLEKIND == LONG_DOUBLE_IS_X86_80_BIT_LITTLE_ENDIAN || \ - LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_LITTLE_ENDIAN + LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_LE_LE # define LONGDOUBLE_LITTLE_ENDIAN # endif # if LONG_DOUBLEKIND == LONG_DOUBLE_IS_IEEE_754_128_BIT_BIG_ENDIAN || \ LONG_DOUBLEKIND == LONG_DOUBLE_IS_X86_80_BIT_BIG_ENDIAN || \ - LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_BIG_ENDIAN + LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_BE_BE # define LONGDOUBLE_BIG_ENDIAN # endif +# if LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_LE_BE || \ + LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_BE_LE +# define LONGDOUBLE_MIX_ENDIAN +# endif + # if LONG_DOUBLEKIND == LONG_DOUBLE_IS_X86_80_BIT_LITTLE_ENDIAN || \ LONG_DOUBLEKIND == LONG_DOUBLE_IS_X86_80_BIT_BIG_ENDIAN # define LONGDOUBLE_X86_80_BIT @@ -6634,8 +6781,10 @@ extern void moncontrol(int); # endif # endif -# if LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_LITTLE_ENDIAN || \ - LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_BIG_ENDIAN +# if LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_LE_LE || \ + LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_BE_BE || \ + LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_LE_BE || \ + LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_BE_LE # define LONGDOUBLE_DOUBLEDOUBLE # endif @@ -6666,6 +6815,9 @@ extern void moncontrol(int); # ifdef LONGDOUBLE_BIG_ENDIAN # define NV_BIG_ENDIAN # endif +# ifdef LONGDOUBLE_MIX_ENDIAN +# define NV_MIX_ENDIAN +# endif #endif /* NaNs (not-a-numbers) can carry payload bits, in addition to @@ -6781,10 +6933,14 @@ extern void moncontrol(int); # define NV_NAN_QS_BYTE_OFFSET 7 # elif LONG_DOUBLEKIND == LONG_DOUBLE_IS_X86_80_BIT_BIG_ENDIAN # define NV_NAN_QS_BYTE_OFFSET 2 -# elif LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_LITTLE_ENDIAN +# elif LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_LE_LE # define NV_NAN_QS_BYTE_OFFSET 13 -# elif LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_BIG_ENDIAN +# elif LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_BE_BE # define NV_NAN_QS_BYTE_OFFSET 1 +# elif LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_LE_BE +# define NV_NAN_QS_BYTE_OFFSET 9 +# elif LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_BE_LE +# define NV_NAN_QS_BYTE_OFFSET 6 # else # error "Unexpected long double format" # endif @@ -6826,8 +6982,10 @@ extern void moncontrol(int); LONG_DOUBLEKIND == LONG_DOUBLE_IS_X86_80_BIT_BIG_ENDIAN) # define NV_NAN_QS_BIT_SHIFT 6 /* 0x40 */ #elif defined(USE_LONG_DOUBLE) && \ - (LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_LITTLE_ENDIAN || \ - LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_BIG_ENDIAN) + (LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_LE_LE || \ + LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_BE_BE || \ + LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_LE_BE || \ + LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_BE_LE) # define NV_NAN_QS_BIT_SHIFT 3 /* 0x08, but not via NV_NAN_BITS */ #else # define NV_NAN_QS_BIT_SHIFT ((NV_NAN_BITS) % 8) /* usually 3, or 0x08 */ @@ -6868,6 +7026,10 @@ extern void moncontrol(int); * 0xFF means "don't go here".*/ /* Shorthands to avoid typoses. */ +#define NV_NAN_PAYLOAD_MASK_SKIP_EIGHT \ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 +#define NV_NAN_PAYLOAD_PERM_SKIP_EIGHT \ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff #define NV_NAN_PAYLOAD_PERM_0_TO_7 \ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 #define NV_NAN_PAYLOAD_PERM_7_TO_0 \ @@ -6946,17 +7108,28 @@ extern void moncontrol(int); # else # error "Unexpected x86 80-bit big-endian long double format" # endif -# elif LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_LITTLE_ENDIAN -/* For double-double we assume only the first double is used for NaN. */ +# elif LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_LE_LE +/* For double-double we assume only the first double (in LE or BE terms) + * is used for NaN. */ # define NV_NAN_PAYLOAD_MASK \ - NV_NAN_PAYLOAD_MASK_IEEE_754_64_LE + NV_NAN_PAYLOAD_MASK_SKIP_EIGHT, NV_NAN_PAYLOAD_MASK_IEEE_754_64_LE # define NV_NAN_PAYLOAD_PERM \ - NV_NAN_PAYLOAD_PERM_IEEE_754_64_LE -# elif LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_BIG_ENDIAN + NV_NAN_PAYLOAD_PERM_SKIP_EIGHT, NV_NAN_PAYLOAD_PERM_IEEE_754_64_LE +# elif LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_BE_BE # define NV_NAN_PAYLOAD_MASK \ NV_NAN_PAYLOAD_MASK_IEEE_754_64_BE # define NV_NAN_PAYLOAD_PERM \ NV_NAN_PAYLOAD_PERM_IEEE_754_64_BE +# elif LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_LE_BE +# define NV_NAN_PAYLOAD_MASK \ + NV_NAN_PAYLOAD_MASK_IEEE_754_64_LE +# define NV_NAN_PAYLOAD_PERM \ + NV_NAN_PAYLOAD_PERM_IEEE_754_64_LE +# elif LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_BE_LE +# define NV_NAN_PAYLOAD_MASK \ + NV_NAN_PAYLOAD_MASK_SKIP_EIGHT, NV_NAN_PAYLOAD_MASK_IEEE_754_64_BE +# define NV_NAN_PAYLOAD_PERM \ + NV_NAN_PAYLOAD_PERM_SKIP_EIGHT, NV_NAN_PAYLOAD_PERM_IEEE_754_64_BE # else # error "Unexpected long double format" # endif