diff -Nru libcoro-perl-6.490/Changes libcoro-perl-6.511/Changes --- libcoro-perl-6.490/Changes 2015-10-16 23:42:34.000000000 +0000 +++ libcoro-perl-6.511/Changes 2016-06-26 21:45:33.000000000 +0000 @@ -3,10 +3,36 @@ TODO: should explore PerlIO::coroaio (perl leaks like hell). TODO: channel->maxsize(newsize)? TODO: __GCC_HAVE_DWARF2_CFI_ASM -TODO: swap_sv, maybe add scope_swap_sv, andallow to unswap by repeat? -TODO: swap_sv not undone in pool +TODO: swap_sv, maybe add scope_swap_sv? TODO: croak when async_pool tries to run canceled thread? +6.511 Sun Jun 26 23:44:50 CEST 2016 + - make it compile with threaded perls again. + - simplify and speed up __DIE__ and __WARN__ handling. + +6.51 Sat Jun 25 20:57:20 CEST 2016 + - 6.5 release didn't compile on most older perls due to + a logic error enabling experimental 5.24 code for all versions. + - since various broken or deficient patches float around + to work around the vtbl API breakage in perl, let's provide + our own workaround, which seems to be much less invasive + and more compatible than the approaches seen so far. YMMV. + - work around assertion failure in perl_destruct on 5.24 + (analyzed by Dave Mitchell). + +6.5 Wed Jun 22 22:23:50 CEST 2016 + - swap_sv swapping order was not symmetrical, causing + wrong swaps when swap_sv was used multiple times on the + same sv in the same thread. + - swap_sv calls can now be undone by calling it again + with the same variables. + - swap_sv calls will now be undone in async_pool threads. + - split Coro::Semaphore::up/adjust into separate xs functions + for better error reporting, at slight codesize increase. + - (libcoro) arm assembly support, please test and report. + - adjust to PL_savestack changes in perl 5.24 (adapted from + the debian patch, which unfortunately gets it wrong). + 6.49 Sat Oct 17 01:40:12 CEST 2015 - throwing an exception to a thread waiting in Coro::Handle using Coro::EV did not stop the watchers, diff -Nru libcoro-perl-6.490/Coro/AIO.pm libcoro-perl-6.511/Coro/AIO.pm --- libcoro-perl-6.490/Coro/AIO.pm 2015-10-16 23:42:40.000000000 +0000 +++ libcoro-perl-6.511/Coro/AIO.pm 2016-06-26 21:45:42.000000000 +0000 @@ -69,7 +69,7 @@ use base Exporter::; -our $VERSION = 6.49; +our $VERSION = 6.511; our @EXPORT = (@IO::AIO::EXPORT, qw(aio_wait)); our @EXPORT_OK = @IO::AIO::EXPORT_OK; diff -Nru libcoro-perl-6.490/Coro/AnyEvent.pm libcoro-perl-6.511/Coro/AnyEvent.pm --- libcoro-perl-6.490/Coro/AnyEvent.pm 2015-10-16 23:42:40.000000000 +0000 +++ libcoro-perl-6.511/Coro/AnyEvent.pm 2016-06-26 21:45:42.000000000 +0000 @@ -163,7 +163,7 @@ use Coro; use AnyEvent (); -our $VERSION = 6.49; +our $VERSION = 6.511; ############################################################################# # idle handler diff -Nru libcoro-perl-6.490/Coro/BDB.pm libcoro-perl-6.511/Coro/BDB.pm --- libcoro-perl-6.490/Coro/BDB.pm 2015-10-16 23:42:40.000000000 +0000 +++ libcoro-perl-6.511/Coro/BDB.pm 2016-06-26 21:45:42.000000000 +0000 @@ -47,7 +47,7 @@ use base Exporter::; -our $VERSION = 6.49; +our $VERSION = 6.511; our $WATCHER; BDB::set_sync_prepare { diff -Nru libcoro-perl-6.490/Coro/Channel.pm libcoro-perl-6.511/Coro/Channel.pm --- libcoro-perl-6.490/Coro/Channel.pm 2015-10-16 23:42:40.000000000 +0000 +++ libcoro-perl-6.511/Coro/Channel.pm 2016-06-26 21:45:42.000000000 +0000 @@ -35,7 +35,7 @@ use Coro (); use Coro::Semaphore (); -our $VERSION = 6.49; +our $VERSION = 6.511; sub DATA (){ 0 } sub SGET (){ 1 } diff -Nru libcoro-perl-6.490/Coro/Debug.pm libcoro-perl-6.511/Coro/Debug.pm --- libcoro-perl-6.490/Coro/Debug.pm 2015-10-16 23:42:40.000000000 +0000 +++ libcoro-perl-6.511/Coro/Debug.pm 2016-06-26 21:45:42.000000000 +0000 @@ -120,7 +120,7 @@ use Coro::AnyEvent (); use Coro::Timer (); -our $VERSION = 6.49; +our $VERSION = 6.511; our %log; our $SESLOGLEVEL = exists $ENV{PERL_CORO_DEFAULT_LOGLEVEL} ? $ENV{PERL_CORO_DEFAULT_LOGLEVEL} : -1; diff -Nru libcoro-perl-6.490/Coro/ecb.h libcoro-perl-6.511/Coro/ecb.h --- libcoro-perl-6.490/Coro/ecb.h 2015-02-18 20:40:27.000000000 +0000 +++ libcoro-perl-6.511/Coro/ecb.h 2015-12-02 08:29:31.000000000 +0000 @@ -42,7 +42,7 @@ #define ECB_H /* 16 bits major, 16 bits minor */ -#define ECB_VERSION 0x00010004 +#define ECB_VERSION 0x00010005 #ifdef _WIN32 typedef signed char int8_t; @@ -69,15 +69,18 @@ #endif #else #include - #if UINTMAX_MAX > 0xffffffffU + #if (defined INTPTR_MAX ? INTPTR_MAX : ULONG_MAX) > 0xffffffffU #define ECB_PTRSIZE 8 #else #define ECB_PTRSIZE 4 #endif #endif +#define ECB_GCC_AMD64 (__amd64 || __amd64__ || __x86_64 || __x86_64__) +#define ECB_MSVC_AMD64 (_M_AMD64 || _M_X64) + /* work around x32 idiocy by defining proper macros */ -#if __amd64 || __x86_64 || _M_AMD64 || _M_X64 +#if ECB_GCC_AMD64 || ECB_MSVC_AMD64 #if _ILP32 #define ECB_AMD64_X32 1 #else @@ -149,27 +152,44 @@ #define ECB_MEMORY_FENCE do { } while (0) #endif +/* http://www-01.ibm.com/support/knowledgecenter/SSGH3R_13.1.0/com.ibm.xlcpp131.aix.doc/compiler_ref/compiler_builtins.html */ +#if __xlC__ && ECB_CPP + #include +#endif + +#if 1400 <= _MSC_VER + #include /* fence functions _ReadBarrier, also bit search functions _BitScanReverse */ +#endif + #ifndef ECB_MEMORY_FENCE #if ECB_GCC_VERSION(2,5) || defined __INTEL_COMPILER || (__llvm__ && __GNUC__) || __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110 #if __i386 || __i386__ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("lock; orb $0, -1(%%esp)" : : : "memory") #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("" : : : "memory") #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("") - #elif __amd64 || __amd64__ || __x86_64 || __x86_64__ + #elif ECB_GCC_AMD64 #define ECB_MEMORY_FENCE __asm__ __volatile__ ("mfence" : : : "memory") #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("" : : : "memory") #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("") #elif __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("sync" : : : "memory") + #elif defined __ARM_ARCH_2__ \ + || defined __ARM_ARCH_3__ || defined __ARM_ARCH_3M__ \ + || defined __ARM_ARCH_4__ || defined __ARM_ARCH_4T__ \ + || defined __ARM_ARCH_5__ || defined __ARM_ARCH_5E__ \ + || defined __ARM_ARCH_5T__ || defined __ARM_ARCH_5TE__ \ + || defined __ARM_ARCH_5TEJ__ + /* should not need any, unless running old code on newer cpu - arm doesn't support that */ #elif defined __ARM_ARCH_6__ || defined __ARM_ARCH_6J__ \ - || defined __ARM_ARCH_6K__ || defined __ARM_ARCH_6ZK__ + || defined __ARM_ARCH_6K__ || defined __ARM_ARCH_6ZK__ \ + || defined __ARM_ARCH_6T2__ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("mcr p15,0,%0,c7,c10,5" : : "r" (0) : "memory") #elif defined __ARM_ARCH_7__ || defined __ARM_ARCH_7A__ \ - || defined __ARM_ARCH_7M__ || defined __ARM_ARCH_7R__ + || defined __ARM_ARCH_7R__ || defined __ARM_ARCH_7M__ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("dmb" : : : "memory") #elif __aarch64__ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("dmb ish" : : : "memory") - #elif (__sparc || __sparc__) && !__sparcv8 + #elif (__sparc || __sparc__) && !(__sparc_v8__ || defined __sparcv8) #define ECB_MEMORY_FENCE __asm__ __volatile__ ("membar #LoadStore | #LoadLoad | #StoreStore | #StoreLoad" : : : "memory") #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("membar #LoadStore | #LoadLoad" : : : "memory") #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("membar #LoadStore | #StoreStore") @@ -351,7 +371,7 @@ #define ecb_deprecated ecb_attribute ((__deprecated__)) #endif -#if __MSC_VER >= 1500 +#if _MSC_VER >= 1500 #define ecb_deprecated_message(msg) __declspec (deprecated (msg)) #elif ECB_GCC_VERSION(4,5) #define ecb_deprecated_message(msg) ecb_attribute ((__deprecated__ (msg)) @@ -369,13 +389,13 @@ #define ecb_const ecb_attribute ((__const__)) #define ecb_pure ecb_attribute ((__pure__)) -/* TODO http://msdn.microsoft.com/en-us/library/k6ktzx3s.aspx __declspec(noreturn) */ #if ECB_C11 || __IBMC_NORETURN - /* http://pic.dhe.ibm.com/infocenter/compbg/v121v141/topic/com.ibm.xlcpp121.bg.doc/language_ref/noreturn.html */ + /* http://www-01.ibm.com/support/knowledgecenter/SSGH3R_13.1.0/com.ibm.xlcpp131.aix.doc/language_ref/noreturn.html */ #define ecb_noreturn _Noreturn #elif ECB_CPP11 #define ecb_noreturn [[noreturn]] #elif _MSC_VER >= 1200 + /* http://msdn.microsoft.com/en-us/library/k6ktzx3s.aspx */ #define ecb_noreturn __declspec (noreturn) #else #define ecb_noreturn ecb_attribute ((__noreturn__)) @@ -417,6 +437,11 @@ ecb_function_ ecb_const int ecb_ctz32 (uint32_t x) { +#if 1400 <= _MSC_VER && (_M_IX86 || _M_X64 || _M_IA64 || _M_ARM) + unsigned long r; + _BitScanForward (&r, x); + return (int)r; +#else int r = 0; x &= ~x + 1; /* this isolates the lowest bit */ @@ -436,14 +461,21 @@ #endif return r; +#endif } ecb_function_ ecb_const int ecb_ctz64 (uint64_t x); ecb_function_ ecb_const int ecb_ctz64 (uint64_t x) { - int shift = x & 0xffffffffU ? 0 : 32; +#if 1400 <= _MSC_VER && (_M_X64 || _M_IA64 || _M_ARM) + unsigned long r; + _BitScanForward64 (&r, x); + return (int)r; +#else + int shift = x & 0xffffffff ? 0 : 32; return ecb_ctz32 (x >> shift) + shift; +#endif } ecb_function_ ecb_const int ecb_popcount32 (uint32_t x); @@ -461,6 +493,11 @@ ecb_function_ ecb_const int ecb_ld32 (uint32_t x); ecb_function_ ecb_const int ecb_ld32 (uint32_t x) { +#if 1400 <= _MSC_VER && (_M_IX86 || _M_X64 || _M_IA64 || _M_ARM) + unsigned long r; + _BitScanReverse (&r, x); + return (int)r; +#else int r = 0; if (x >> 16) { x >>= 16; r += 16; } @@ -470,16 +507,23 @@ if (x >> 1) { r += 1; } return r; +#endif } ecb_function_ ecb_const int ecb_ld64 (uint64_t x); ecb_function_ ecb_const int ecb_ld64 (uint64_t x) { +#if 1400 <= _MSC_VER && (_M_X64 || _M_IA64 || _M_ARM) + unsigned long r; + _BitScanReverse64 (&r, x); + return (int)r; +#else int r = 0; if (x >> 32) { x >>= 32; r += 32; } return r + ecb_ld32 (x); +#endif } #endif @@ -546,9 +590,18 @@ ecb_inline ecb_const uint64_t ecb_rotr64 (uint64_t x, unsigned int count) { return (x << (64 - count)) | (x >> count); } #if ECB_GCC_VERSION(4,3) || (ECB_CLANG_BUILTIN(__builtin_bswap32) && ECB_CLANG_BUILTIN(__builtin_bswap64)) + #if ECB_GCC_VERSION(4,8) || ECB_CLANG_BUILTIN(__builtin_bswap16) + #define ecb_bswap16(x) __builtin_bswap16 (x) + #else #define ecb_bswap16(x) (__builtin_bswap32 (x) >> 16) + #endif #define ecb_bswap32(x) __builtin_bswap32 (x) #define ecb_bswap64(x) __builtin_bswap64 (x) +#elif _MSC_VER + #include + #define ecb_bswap16(x) ((uint16_t)_byteswap_ushort ((uint16_t)(x))) + #define ecb_bswap32(x) ((uint32_t)_byteswap_ulong ((uint32_t)(x))) + #define ecb_bswap64(x) ((uint64_t)_byteswap_uint64 ((uint64_t)(x))) #else ecb_function_ ecb_const uint16_t ecb_bswap16 (uint16_t x); ecb_function_ ecb_const uint16_t @@ -583,8 +636,8 @@ /* try to tell the compiler that some condition is definitely true */ #define ecb_assume(cond) if (!(cond)) ecb_unreachable (); else 0 -ecb_inline ecb_const unsigned char ecb_byteorder_helper (void); -ecb_inline ecb_const unsigned char +ecb_inline ecb_const uint32_t ecb_byteorder_helper (void); +ecb_inline ecb_const uint32_t ecb_byteorder_helper (void) { /* the union code still generates code under pressure in gcc, */ @@ -593,26 +646,28 @@ /* the reason why we have this horrible preprocessor mess */ /* is to avoid it in all cases, at least on common architectures */ /* or when using a recent enough gcc version (>= 4.6) */ -#if __i386 || __i386__ || _M_X86 || __amd64 || __amd64__ || _M_X64 - return 0x44; -#elif __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - return 0x44; -#elif __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - return 0x11; +#if (defined __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) \ + || ((__i386 || __i386__ || _M_IX86 || ECB_GCC_AMD64 || ECB_MSVC_AMD64) && !__VOS__) + #define ECB_LITTLE_ENDIAN 1 + return 0x44332211; +#elif (defined __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) \ + || ((__AARCH64EB__ || __MIPSEB__ || __ARMEB__) && !__VOS__) + #define ECB_BIG_ENDIAN 1 + return 0x11223344; #else union { - uint32_t i; - uint8_t c; - } u = { 0x11223344 }; - return u.c; + uint8_t c[4]; + uint32_t u; + } u = { 0x11, 0x22, 0x33, 0x44 }; + return u.u; #endif } ecb_inline ecb_const ecb_bool ecb_big_endian (void); -ecb_inline ecb_const ecb_bool ecb_big_endian (void) { return ecb_byteorder_helper () == 0x11; } +ecb_inline ecb_const ecb_bool ecb_big_endian (void) { return ecb_byteorder_helper () == 0x11223344; } ecb_inline ecb_const ecb_bool ecb_little_endian (void); -ecb_inline ecb_const ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () == 0x44; } +ecb_inline ecb_const ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () == 0x44332211; } #if ECB_GCC_VERSION(3,0) || ECB_C99 #define ecb_mod(m,n) ((m) % (n) + ((m) % (n) < 0 ? (n) : 0)) @@ -647,6 +702,102 @@ #define ecb_array_length(name) (sizeof (name) / sizeof (name [0])) #endif +ecb_function_ ecb_const uint32_t ecb_binary16_to_binary32 (uint32_t x); +ecb_function_ ecb_const uint32_t +ecb_binary16_to_binary32 (uint32_t x) +{ + unsigned int s = (x & 0x8000) << (31 - 15); + int e = (x >> 10) & 0x001f; + unsigned int m = x & 0x03ff; + + if (ecb_expect_false (e == 31)) + /* infinity or NaN */ + e = 255 - (127 - 15); + else if (ecb_expect_false (!e)) + { + if (ecb_expect_true (!m)) + /* zero, handled by code below by forcing e to 0 */ + e = 0 - (127 - 15); + else + { + /* subnormal, renormalise */ + unsigned int s = 10 - ecb_ld32 (m); + + m = (m << s) & 0x3ff; /* mask implicit bit */ + e -= s - 1; + } + } + + /* e and m now are normalised, or zero, (or inf or nan) */ + e += 127 - 15; + + return s | (e << 23) | (m << (23 - 10)); +} + +ecb_function_ ecb_const uint16_t ecb_binary32_to_binary16 (uint32_t x); +ecb_function_ ecb_const uint16_t +ecb_binary32_to_binary16 (uint32_t x) +{ + unsigned int s = (x >> 16) & 0x00008000; /* sign bit, the easy part */ + unsigned int e = ((x >> 23) & 0x000000ff) - (127 - 15); /* the desired exponent */ + unsigned int m = x & 0x007fffff; + + x &= 0x7fffffff; + + /* if it's within range of binary16 normals, use fast path */ + if (ecb_expect_true (0x38800000 <= x && x <= 0x477fefff)) + { + /* mantissa round-to-even */ + m += 0x00000fff + ((m >> (23 - 10)) & 1); + + /* handle overflow */ + if (ecb_expect_false (m >= 0x00800000)) + { + m >>= 1; + e += 1; + } + + return s | (e << 10) | (m >> (23 - 10)); + } + + /* handle large numbers and infinity */ + if (ecb_expect_true (0x477fefff < x && x <= 0x7f800000)) + return s | 0x7c00; + + /* handle zero, subnormals and small numbers */ + if (ecb_expect_true (x < 0x38800000)) + { + /* zero */ + if (ecb_expect_true (!x)) + return s; + + /* handle subnormals */ + + /* too small, will be zero */ + if (e < (14 - 24)) /* might not be sharp, but is good enough */ + return s; + + m |= 0x00800000; /* make implicit bit explicit */ + + /* very tricky - we need to round to the nearest e (+10) bit value */ + { + unsigned int bits = 14 - e; + unsigned int half = (1 << (bits - 1)) - 1; + unsigned int even = (m >> bits) & 1; + + /* if this overflows, we will end up with a normalised number */ + m = (m + half + even) >> bits; + } + + return s | m; + } + + /* handle NaNs, preserve leftmost nan bits, but make sure we don't turn them into infinities */ + m >>= 13; + + return s | 0x7c00 | m | !m; +} + /*******************************************************************************/ /* floating point stuff, can be disabled by defining ECB_NO_LIBM */ @@ -654,7 +805,7 @@ /* the only noteworthy exception is ancient armle, which uses order 43218765 */ #if 0 \ || __i386 || __i386__ \ - || __amd64 || __amd64__ || __x86_64 || __x86_64__ \ + || ECB_GCC_AMD64 \ || __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__ \ || defined __s390__ || defined __s390x__ \ || defined __mips__ \ @@ -664,7 +815,7 @@ || defined __m68k__ \ || defined __m88k__ \ || defined __sh__ \ - || defined _M_IX86 || defined _M_AMD64 || defined _M_IA64 \ + || defined _M_IX86 || defined ECB_MSVC_AMD64 || defined _M_IA64 \ || (defined __arm__ && (defined __ARM_EABI__ || defined __EABI__ || defined __VFP_FP__ || defined _WIN32_WCE || defined __ANDROID__)) \ || defined __aarch64__ #define ECB_STDFP 1 @@ -692,27 +843,12 @@ #if ECB_C99 || _XOPEN_VERSION >= 600 || _POSIX_VERSION >= 200112L #define ecb_ldexpf(x,e) ldexpf ((x), (e)) + #define ecb_frexpf(x,e) frexpf ((x), (e)) #else - #define ecb_ldexpf(x,e) (float) ldexp ((x), (e)) + #define ecb_ldexpf(x,e) (float) ldexp ((double) (x), (e)) + #define ecb_frexpf(x,e) (float) frexp ((double) (x), (e)) #endif - /* converts an ieee half/binary16 to a float */ - ecb_function_ ecb_const float ecb_binary16_to_float (uint16_t x); - ecb_function_ ecb_const float - ecb_binary16_to_float (uint16_t x) - { - int e = (x >> 10) & 0x1f; - int m = x & 0x3ff; - float r; - - if (!e ) r = ecb_ldexpf (m , -24); - else if (e != 31) r = ecb_ldexpf (m + 0x400, e - 25); - else if (m ) r = ECB_NAN; - else r = ECB_INFINITY; - - return x & 0x8000 ? -r : r; - } - /* convert a float to ieee single/binary32 */ ecb_function_ ecb_const uint32_t ecb_float_to_binary32 (float x); ecb_function_ ecb_const uint32_t @@ -732,7 +868,7 @@ if (x < -3.40282346638528860e+38f) return 0xff800000U; if (x != x ) return 0x7fbfffffU; - m = frexpf (x, &e) * 0x1000000U; + m = ecb_frexpf (x, &e) * 0x1000000U; r = m & 0x80000000U; @@ -853,6 +989,22 @@ return r; } + /* convert a float to ieee half/binary16 */ + ecb_function_ ecb_const uint16_t ecb_float_to_binary16 (float x); + ecb_function_ ecb_const uint16_t + ecb_float_to_binary16 (float x) + { + return ecb_binary32_to_binary16 (ecb_float_to_binary32 (x)); + } + + /* convert an ieee half/binary16 to float */ + ecb_function_ ecb_const float ecb_binary16_to_float (uint16_t x); + ecb_function_ ecb_const float + ecb_binary16_to_float (uint16_t x) + { + return ecb_binary32_to_float (ecb_binary16_to_binary32 (x)); + } + #endif #endif diff -Nru libcoro-perl-6.490/Coro/Handle.pm libcoro-perl-6.511/Coro/Handle.pm --- libcoro-perl-6.490/Coro/Handle.pm 2015-10-16 23:42:40.000000000 +0000 +++ libcoro-perl-6.511/Coro/Handle.pm 2016-06-26 21:45:42.000000000 +0000 @@ -46,7 +46,7 @@ use base 'Exporter'; -our $VERSION = 6.49; +our $VERSION = 6.511; our @EXPORT = qw(unblock); =item $fh = new_from_fh Coro::Handle $fhandle [, arg => value...] diff -Nru libcoro-perl-6.490/Coro/libcoro/coro.c libcoro-perl-6.511/Coro/libcoro/coro.c --- libcoro-perl-6.490/Coro/libcoro/coro.c 2012-12-21 04:57:20.000000000 +0000 +++ libcoro-perl-6.511/Coro/libcoro/coro.c 2015-12-10 10:24:21.000000000 +0000 @@ -117,6 +117,13 @@ # if CORO_ASM + #if __arm__ && \ + (defined __ARM_ARCH_7__ || defined __ARM_ARCH_7A__ \ + || defined __ARM_ARCH_7R__ || defined __ARM_ARCH_7M__ \ + || __ARCH_ARCH == 7) + #define CORO_ARM 1 + #endif + #if _WIN32 || __CYGWIN__ #define CORO_WIN_TIB 1 #endif @@ -206,7 +213,7 @@ "\tpopq %rcx\n" "\tjmpq *%rcx\n" - #elif __i386 + #elif __i386__ #define NUM_SAVED 4 "\tpushl %ebp\n" @@ -234,6 +241,80 @@ "\tpopl %ecx\n" "\tjmpl *%ecx\n" + #elif CORO_ARM /* untested, what about thumb, neon, iwmmxt? */ + + #if __ARM_PCS_VFP + "\tvpush {d8-d15}\n" + #define NUM_SAVED (9 + 8 * 2) + #else + #define NUM_SAVED 9 + #endif + "\tpush {r4-r11,lr}\n" + "\tstr sp, [r0]\n" + "\tldr sp, [r1]\n" + "\tpop {r4-r11,lr}\n" + #if __ARM_PCS_VFP + "\tvpop {d8-d15}\n" + #endif + "\tmov r15, lr\n" + + #elif __mips__ && 0 /* untested, 32 bit only */ + + #define NUM_SAVED (12 + 8 * 2) + /* TODO: n64/o64, lw=>ld */ + + "\t.set nomips16\n" + "\t.frame $sp,112,$31\n" + #if __mips_soft_float + "\taddiu $sp,$sp,-44\n" + #else + "\taddiu $sp,$sp,-112\n" + "\ts.d $f30,88($sp)\n" + "\ts.d $f28,80($sp)\n" + "\ts.d $f26,72($sp)\n" + "\ts.d $f24,64($sp)\n" + "\ts.d $f22,56($sp)\n" + "\ts.d $f20,48($sp)\n" + #endif + "\tsw $28,40($sp)\n" + "\tsw $31,36($sp)\n" + "\tsw $fp,32($sp)\n" + "\tsw $23,28($sp)\n" + "\tsw $22,24($sp)\n" + "\tsw $21,20($sp)\n" + "\tsw $20,16($sp)\n" + "\tsw $19,12($sp)\n" + "\tsw $18,8($sp)\n" + "\tsw $17,4($sp)\n" + "\tsw $16,0($sp)\n" + "\tsw $sp,0($4)\n" + "\tlw $sp,0($5)\n" + #if !__mips_soft_float + "\tl.d $f30,88($sp)\n" + "\tl.d $f28,80($sp)\n" + "\tl.d $f26,72($sp)\n" + "\tl.d $f24,64($sp)\n" + "\tl.d $f22,56($sp)\n" + "\tl.d $f20,48($sp)\n" + #endif + "\tlw $28,40($sp)\n" + "\tlw $31,36($sp)\n" + "\tlw $fp,32($sp)\n" + "\tlw $23,28($sp)\n" + "\tlw $22,24($sp)\n" + "\tlw $21,20($sp)\n" + "\tlw $20,16($sp)\n" + "\tlw $19,12($sp)\n" + "\tlw $18,8($sp)\n" + "\tlw $17,4($sp)\n" + "\tlw $16,0($sp)\n" + "\tj $31\n" + #if __mips_soft_float + "\taddiu $sp,$sp,44\n" + #else + "\taddiu $sp,$sp,112\n" + #endif + #else #error unsupported architecture #endif @@ -313,10 +394,10 @@ # elif CORO_LOSER coro_setjmp (ctx->env); - #if __CYGWIN__ && __i386 + #if __CYGWIN__ && __i386__ ctx->env[8] = (long) coro_init; ctx->env[7] = (long) ((char *)sptr + ssize) - sizeof (long); - #elif __CYGWIN__ && __x86_64 + #elif __CYGWIN__ && __x86_64__ ctx->env[7] = (long) coro_init; ctx->env[6] = (long) ((char *)sptr + ssize) - sizeof (long); #elif defined __MINGW32__ @@ -347,7 +428,7 @@ #elif defined (__GNU_LIBRARY__) && defined (__i386__) ctx->env[0].__jmpbuf[0].__pc = (char *) coro_init; ctx->env[0].__jmpbuf[0].__sp = (void *) ((char *)sptr + ssize) - sizeof (long); - #elif defined (__GNU_LIBRARY__) && defined (__amd64__) + #elif defined (__GNU_LIBRARY__) && defined (__x86_64__) ctx->env[0].__jmpbuf[JB_PC] = (long) coro_init; ctx->env[0].__jmpbuf[0].__sp = (void *) ((char *)sptr + ssize) - sizeof (long); #else @@ -362,19 +443,34 @@ # elif CORO_ASM - ctx->sp = (void **)(ssize + (char *)sptr); - *--ctx->sp = (void *)abort; /* needed for alignment only */ - *--ctx->sp = (void *)coro_init; - - #if CORO_WIN_TIB - *--ctx->sp = 0; /* ExceptionList */ - *--ctx->sp = (char *)sptr + ssize; /* StackBase */ - *--ctx->sp = sptr; /* StackLimit */ + #if __i386__ || __x86_64__ + ctx->sp = (void **)(ssize + (char *)sptr); + *--ctx->sp = (void *)abort; /* needed for alignment only */ + *--ctx->sp = (void *)coro_init; + #if CORO_WIN_TIB + *--ctx->sp = 0; /* ExceptionList */ + *--ctx->sp = (char *)sptr + ssize; /* StackBase */ + *--ctx->sp = sptr; /* StackLimit */ + #endif + #elif CORO_ARM + /* return address stored in lr register, don't push anything */ + #else + #error unsupported architecture #endif ctx->sp -= NUM_SAVED; memset (ctx->sp, 0, sizeof (*ctx->sp) * NUM_SAVED); + #if __i386__ || __x86_64__ + /* done already */ + #elif CORO_ARM + ctx->sp[0] = coro; /* r4 */ + ctx->sp[1] = arg; /* r5 */ + ctx->sp[8] = (char *)coro_init; /* lr */ + #else + #error unsupported architecture + #endif + # elif CORO_UCONTEXT getcontext (&(ctx->uc)); @@ -602,7 +698,7 @@ # undef CORO_GUARDPAGES #endif -#if !__i386 && !__x86_64 && !__powerpc && !__m68k && !__alpha && !__mips && !__sparc64 +#if !__i386__ && !__x86_64__ && !__powerpc__ && !__arm__ && !__aarch64__ && !__m68k__ && !__alpha__ && !__mips__ && !__sparc64__ # undef CORO_GUARDPAGES #endif diff -Nru libcoro-perl-6.490/Coro/libcoro/coro.h libcoro-perl-6.511/Coro/libcoro/coro.h --- libcoro-perl-6.490/Coro/libcoro/coro.h 2012-12-21 04:47:31.000000000 +0000 +++ libcoro-perl-6.511/Coro/libcoro/coro.h 2015-12-05 22:07:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2012 Marc Alexander Lehmann + * Copyright (c) 2001-2012,2015 Marc Alexander Lehmann * * Redistribution and use in source and binary forms, with or without modifica- * tion, are permitted provided that the following conditions are met: @@ -79,6 +79,9 @@ * 2012-12-05 experimental fiber backend (allocates stack twice). * 2012-12-07 API version 3 - add coro_stack_alloc/coro_stack_free. * 2012-12-21 valgrind stack registering was broken. + * 2015-12-05 experimental asm be for arm7, based on a patch by Nick Zavaritsky. + * use __name__ for predefined symbols, as in libecb. + * enable guard pages on arm, aarch64 and mips. */ #ifndef CORO_H @@ -140,8 +143,8 @@ * -DCORO_ASM * * Hand coded assembly, known to work only on a few architectures/ABI: - * GCC + x86/IA32 and amd64/x86_64 + GNU/Linux and a few BSDs. Fastest choice, - * if it works. + * GCC + arm7/x86/IA32/amd64/x86_64 + GNU/Linux and a few BSDs. Fastest + * choice, if it works. * * -DCORO_PTHREAD * @@ -299,11 +302,11 @@ && !defined CORO_SJLJ && !defined CORO_LINUX \ && !defined CORO_IRIX && !defined CORO_ASM \ && !defined CORO_PTHREAD && !defined CORO_FIBER -# if defined WINDOWS && (defined __i386 || (__x86_64 || defined _M_IX86 || defined _M_AMD64) +# if defined WINDOWS && (defined __i386__ || (__x86_64__ || defined _M_IX86 || defined _M_AMD64) # define CORO_ASM 1 # elif defined WINDOWS || defined _WIN32 # define CORO_LOSER 1 /* you don't win with windoze */ -# elif __linux && (__i386 || (__x86_64 && !__ILP32)) +# elif __linux && (__i386__ || (__x86_64__ && !__ILP32__) || (__arm__ && __ARCH_ARCH == 7)) # define CORO_ASM 1 # elif defined HAVE_UCONTEXT_H # define CORO_UCONTEXT 1 @@ -375,7 +378,11 @@ void **sp; /* must be at offset 0 */ }; +#if __i386__ || __x86_64__ void __attribute__ ((__noinline__, __regparm__(2))) +#else +void __attribute__ ((__noinline__)) +#endif coro_transfer (coro_context *prev, coro_context *next); # define coro_destroy(ctx) (void *)(ctx) diff -Nru libcoro-perl-6.490/Coro/LWP.pm libcoro-perl-6.511/Coro/LWP.pm --- libcoro-perl-6.490/Coro/LWP.pm 2015-10-16 23:42:40.000000000 +0000 +++ libcoro-perl-6.511/Coro/LWP.pm 2016-06-26 21:45:42.000000000 +0000 @@ -126,7 +126,7 @@ use Net::FTP (); use Net::NNTP (); -our $VERSION = 6.49; +our $VERSION = 6.511; *Socket::inet_aton = \&Coro::Util::inet_aton; diff -Nru libcoro-perl-6.490/Coro/MakeMaker.pm libcoro-perl-6.511/Coro/MakeMaker.pm --- libcoro-perl-6.490/Coro/MakeMaker.pm 2015-10-16 23:42:40.000000000 +0000 +++ libcoro-perl-6.511/Coro/MakeMaker.pm 2016-06-26 21:45:42.000000000 +0000 @@ -7,7 +7,7 @@ our $installsitearch; -our $VERSION = 6.49; +our $VERSION = 6.511; our @EXPORT_OK = qw(&coro_args $installsitearch); my %opt; diff -Nru libcoro-perl-6.490/Coro/RWLock.pm libcoro-perl-6.511/Coro/RWLock.pm --- libcoro-perl-6.490/Coro/RWLock.pm 2015-10-16 23:42:40.000000000 +0000 +++ libcoro-perl-6.511/Coro/RWLock.pm 2016-06-26 21:45:42.000000000 +0000 @@ -38,7 +38,7 @@ use Coro (); -our $VERSION = 6.49; +our $VERSION = 6.511; =item $l = new Coro::RWLock; diff -Nru libcoro-perl-6.490/Coro/Select.pm libcoro-perl-6.511/Coro/Select.pm --- libcoro-perl-6.490/Coro/Select.pm 2015-10-16 23:42:40.000000000 +0000 +++ libcoro-perl-6.511/Coro/Select.pm 2016-06-26 21:45:42.000000000 +0000 @@ -67,7 +67,7 @@ use base Exporter::; -our $VERSION = 6.49; +our $VERSION = 6.511; our @EXPORT_OK = "select"; sub import { diff -Nru libcoro-perl-6.490/Coro/Semaphore.pm libcoro-perl-6.511/Coro/Semaphore.pm --- libcoro-perl-6.490/Coro/Semaphore.pm 2015-10-16 23:42:40.000000000 +0000 +++ libcoro-perl-6.511/Coro/Semaphore.pm 2016-06-26 21:45:42.000000000 +0000 @@ -42,7 +42,7 @@ use Coro (); -our $VERSION = 6.49; +our $VERSION = 6.511; =item new [inital count] diff -Nru libcoro-perl-6.490/Coro/SemaphoreSet.pm libcoro-perl-6.511/Coro/SemaphoreSet.pm --- libcoro-perl-6.490/Coro/SemaphoreSet.pm 2015-10-16 23:42:40.000000000 +0000 +++ libcoro-perl-6.511/Coro/SemaphoreSet.pm 2016-06-26 21:45:42.000000000 +0000 @@ -35,7 +35,7 @@ use common::sense; -our $VERSION = 6.49; +our $VERSION = 6.511; use Coro::Semaphore (); diff -Nru libcoro-perl-6.490/Coro/Signal.pm libcoro-perl-6.511/Coro/Signal.pm --- libcoro-perl-6.490/Coro/Signal.pm 2015-10-16 23:42:40.000000000 +0000 +++ libcoro-perl-6.511/Coro/Signal.pm 2016-06-26 21:45:42.000000000 +0000 @@ -38,7 +38,7 @@ use Coro::Semaphore (); -our $VERSION = 6.49; +our $VERSION = 6.511; =item $sig = new Coro::Signal; diff -Nru libcoro-perl-6.490/Coro/Socket.pm libcoro-perl-6.511/Coro/Socket.pm --- libcoro-perl-6.490/Coro/Socket.pm 2015-10-16 23:42:40.000000000 +0000 +++ libcoro-perl-6.511/Coro/Socket.pm 2016-06-26 21:45:42.000000000 +0000 @@ -73,7 +73,7 @@ use base qw(Coro::Handle IO::Socket::INET); -our $VERSION = 6.49; +our $VERSION = 6.511; our (%_proto, %_port); diff -Nru libcoro-perl-6.490/Coro/Specific.pm libcoro-perl-6.511/Coro/Specific.pm --- libcoro-perl-6.490/Coro/Specific.pm 2015-10-16 23:42:40.000000000 +0000 +++ libcoro-perl-6.511/Coro/Specific.pm 2016-06-26 21:45:42.000000000 +0000 @@ -36,7 +36,7 @@ use common::sense; -our $VERSION = 6.49; +our $VERSION = 6.511; =item new diff -Nru libcoro-perl-6.490/Coro/State.pm libcoro-perl-6.511/Coro/State.pm --- libcoro-perl-6.490/Coro/State.pm 2015-10-16 23:42:40.000000000 +0000 +++ libcoro-perl-6.511/Coro/State.pm 2016-06-26 21:45:42.000000000 +0000 @@ -93,7 +93,7 @@ use XSLoader; BEGIN { - our $VERSION = 6.49; + our $VERSION = 6.511; # must be done here because the xs part expects it to exist # it might exist already because Coro::Specific created it. @@ -315,6 +315,16 @@ my %private_hash; $coro->swap_sv (\%some_hash, \%private_hash); +To undo an earlier C call you must call C with exactly +the same two variables in the same order (the references can be different, +it's the variables that they point to that count). For example, the +following sequence will remove the swap of C<$x> and C<$y>, while keeping +the swap of C<$x> and C<$z>: + + $coro->swap-sv (\$x, \$y); + $coro->swap-sv (\$x, \$z); + $coro->swap-sv (\$x, \$y); + =item $bytes = $state->rss Returns the memory allocated by the coro (which includes static @@ -481,14 +491,14 @@ Which could be used to implement a loop like this: async { - my $n; + my $n; my $l = callcc sub { $_[0] }; - $n++; + $n++; print "iteration $n\n"; $l->($l) unless $n == 10; - }; + }; If you find this confusing, then you already understand the coolness of call/cc: It can turn anything into spaghetti code real fast. diff -Nru libcoro-perl-6.490/Coro/State.xs libcoro-perl-6.511/Coro/State.xs --- libcoro-perl-6.490/Coro/State.xs 2015-10-16 07:33:17.000000000 +0000 +++ libcoro-perl-6.511/Coro/State.xs 2016-06-26 21:44:30.000000000 +0000 @@ -118,6 +118,12 @@ # endif #endif +/* perl usually suppressed asserts. for debugging, we sometimes force it to be on */ +#if 0 +# undef NDEBUG +# include +#endif + static double (*nvtime)(); /* so why doesn't it take void? */ static void (*u2time)(pTHX_ UV ret[2]); @@ -728,7 +734,7 @@ /* swap sv heads, at least logically */ static void -swap_svs (pTHX_ Coro__State c) +swap_svs_enter (pTHX_ Coro__State c) { int i; @@ -736,9 +742,22 @@ swap_sv (AvARRAY (c->swap_sv)[i], AvARRAY (c->swap_sv)[i + 1]); } -#define SWAP_SVS(coro) \ +static void +swap_svs_leave (pTHX_ Coro__State c) +{ + int i; + + for (i = AvFILLp (c->swap_sv) - 1; i >= 0; i -= 2) + swap_sv (AvARRAY (c->swap_sv)[i], AvARRAY (c->swap_sv)[i + 1]); +} + +#define SWAP_SVS_ENTER(coro) \ + if (ecb_expect_false ((coro)->swap_sv)) \ + swap_svs_enter (aTHX_ (coro)) + +#define SWAP_SVS_LEAVE(coro) \ if (ecb_expect_false ((coro)->swap_sv)) \ - swap_svs (aTHX_ (coro)) + swap_svs_leave (aTHX_ (coro)) static void on_enterleave_call (pTHX_ SV *cb); @@ -801,13 +820,13 @@ ((coro_enterleave_hook)AvARRAY (c->on_enter_xs)[i]) (aTHX_ AvARRAY (c->on_enter_xs)[i + 1]); } - SWAP_SVS (c); + SWAP_SVS_ENTER (c); } static void save_perl (pTHX_ Coro__State c) { - SWAP_SVS (c); + SWAP_SVS_LEAVE (c); if (ecb_expect_false (c->on_leave_xs)) { @@ -952,6 +971,11 @@ New(54,PL_savestack,24,ANY); PL_savestack_ix = 0; PL_savestack_max = 24; +#if PERL_VERSION_ATLEAST (5,24,0) + /* perl 5.24 moves SS_MAXPUSH optimisation from */ + /* the header macros to PL_savestack_max */ + PL_savestack_max -= SS_MAXPUSH; +#endif #if !PERL_VERSION_ATLEAST (5,10,0) New(54,PL_retstack,4,OP*); @@ -1027,11 +1051,7 @@ return rss; } -/** coroutine stack handling ************************************************/ - -static int (*orig_sigelem_get) (pTHX_ SV *sv, MAGIC *mg); -static int (*orig_sigelem_set) (pTHX_ SV *sv, MAGIC *mg); -static int (*orig_sigelem_clr) (pTHX_ SV *sv, MAGIC *mg); +/** provide custom get/set/clear methods for %SIG elements ******************/ /* apparently < 5.8.8 */ #ifndef MgPV_nolen_const @@ -1040,6 +1060,34 @@ (const char*)(mg)->mg_ptr) #endif +/* this will be a patched copy of PL_vtbl_sigelem */ +static MGVTBL coro_sigelem_vtbl; + +static int ecb_cold +coro_sig_copy (pTHX_ SV *sv, MAGIC *mg, SV *nsv, const char *name, I32 namlen) +{ + char *key = SvPV_nolen ((SV *)name); + + /* do what mg_copy normally does */ + sv_magic (nsv, mg->mg_obj, PERL_MAGIC_sigelem, name, namlen); + assert (mg_find (nsv, PERL_MAGIC_sigelem)->mg_virtual == &PL_vtbl_sigelem); + + /* patch sigelem vtbl, but only for __WARN__ and __DIE__ */ + if (*key == '_' + && (strEQ (key, "__DIE__") + || strEQ (key, "__WARN__"))) + mg_find (nsv, PERL_MAGIC_sigelem)->mg_virtual = &coro_sigelem_vtbl; + + return 1; +} + +/* perl does not have a %SIG vtbl, we provide one so we can override */ +/* the magic vtbl for the __DIE__ and __WARN__ members */ +static const MGVTBL coro_sig_vtbl = { + 0, 0, 0, 0, 0, + coro_sig_copy +}; + /* * This overrides the default magic get method of %SIG elements. * The original one doesn't provide for reading back of PL_diehook/PL_warnhook @@ -1050,79 +1098,46 @@ coro_sigelem_get (pTHX_ SV *sv, MAGIC *mg) { const char *s = MgPV_nolen_const (mg); + /* the key must be either __DIE__ or __WARN__ here */ + SV **svp = s[2] == 'D' ? &PL_diehook : &PL_warnhook; - if (*s == '_') - { - SV **svp = 0; - - if (strEQ (s, "__DIE__" )) svp = &PL_diehook; - if (strEQ (s, "__WARN__")) svp = &PL_warnhook; - - if (svp) - { - SV *ssv; - - if (!*svp) - ssv = &PL_sv_undef; - else if (SvTYPE (*svp) == SVt_PVCV) /* perlio directly stores a CV in warnhook. ugh. */ - ssv = sv_2mortal (newRV_inc (*svp)); - else - ssv = *svp; + SV *ssv; - sv_setsv (sv, ssv); - return 0; - } - } + if (!*svp) + ssv = &PL_sv_undef; + else if (SvTYPE (*svp) == SVt_PVCV) /* perlio directly stores a CV in warnhook. ugh. */ + ssv = sv_2mortal (newRV_inc (*svp)); + else + ssv = *svp; - return orig_sigelem_get ? orig_sigelem_get (aTHX_ sv, mg) : 0; + sv_setsv (sv, ssv); + return 0; } static int ecb_cold coro_sigelem_clr (pTHX_ SV *sv, MAGIC *mg) { const char *s = MgPV_nolen_const (mg); + /* the key must be either __DIE__ or __WARN__ here */ + SV **svp = s[2] == 'D' ? &PL_diehook : &PL_warnhook; - if (*s == '_') - { - SV **svp = 0; - - if (strEQ (s, "__DIE__" )) svp = &PL_diehook; - if (strEQ (s, "__WARN__")) svp = &PL_warnhook; - - if (svp) - { - SV *old = *svp; - *svp = 0; - SvREFCNT_dec (old); - return 0; - } - } - - return orig_sigelem_clr ? orig_sigelem_clr (aTHX_ sv, mg) : 0; + SV *old = *svp; + *svp = 0; + SvREFCNT_dec (old); + return 0; } static int ecb_cold coro_sigelem_set (pTHX_ SV *sv, MAGIC *mg) { const char *s = MgPV_nolen_const (mg); + /* the key must be either __DIE__ or __WARN__ here */ + SV **svp = s[2] == 'D' ? &PL_diehook : &PL_warnhook; - if (*s == '_') - { - SV **svp = 0; - - if (strEQ (s, "__DIE__" )) svp = &PL_diehook; - if (strEQ (s, "__WARN__")) svp = &PL_warnhook; - - if (svp) - { - SV *old = *svp; - *svp = SvOK (sv) ? newSVsv (sv) : 0; - SvREFCNT_dec (old); - return 0; - } - } - - return orig_sigelem_set ? orig_sigelem_set (aTHX_ sv, mg) : 0; + SV *old = *svp; + *svp = SvOK (sv) ? newSVsv (sv) : 0; + SvREFCNT_dec (old); + return 0; } static void @@ -1144,6 +1159,8 @@ return 1; } +/** coroutine stack handling ************************************************/ + static UNOP init_perl_op; ecb_noinline static void /* noinline to keep it out of the transfer fast path */ @@ -1219,7 +1236,7 @@ /* copy throw, in case it was set before init_perl */ CORO_THROW = coro->except; - SWAP_SVS (coro); + SWAP_SVS_ENTER (coro); if (ecb_expect_false (enable_times)) { @@ -1267,10 +1284,10 @@ load_perl (aTHX_ coro); - coro_unwind_stacks (aTHX); - /* restore swapped sv's */ - SWAP_SVS (coro); + SWAP_SVS_LEAVE (coro); + + coro_unwind_stacks (aTHX); coro_destruct_stacks (aTHX); @@ -1527,6 +1544,13 @@ */ /* + * pp_entersub in 5.24 no longer ENTERs, but perl_destruct + * requires PL_scopestack_ix, so do it here if required. + */ + if (!PL_scopestack_ix) + ENTER; + + /* * If perl-run returns we assume exit() was being called or the coro * fell off the end, which seems to be the only valid (non-bug) * reason for perl_run to return. We try to mimic whatever perl is normally @@ -2415,9 +2439,16 @@ av_clear (GvAV (PL_defgv)); hv_store (hv, "desc", sizeof ("desc") - 1, SvREFCNT_inc_NN (sv_async_pool_idle), 0); + if (ecb_expect_false (coro->swap_sv)) + { + SWAP_SVS_LEAVE (coro); + SvREFCNT_dec_NN (coro->swap_sv); + coro->swap_sv = 0; + } + coro->prio = 0; - if (coro->cctx && (coro->cctx->flags & CC_TRACE)) + if (ecb_expect_false (coro->cctx) && ecb_expect_false (coro->cctx->flags & CC_TRACE)) api_trace (aTHX_ coro_current, 0); frame->prepare = prepare_schedule; @@ -3601,9 +3632,30 @@ irsgv = gv_fetchpv ("/" , GV_ADD|GV_NOTQUAL, SVt_PV); stdoutgv = gv_fetchpv ("STDOUT", GV_ADD|GV_NOTQUAL, SVt_PVIO); - orig_sigelem_get = PL_vtbl_sigelem.svt_get; PL_vtbl_sigelem.svt_get = coro_sigelem_get; - orig_sigelem_set = PL_vtbl_sigelem.svt_set; PL_vtbl_sigelem.svt_set = coro_sigelem_set; - orig_sigelem_clr = PL_vtbl_sigelem.svt_clear; PL_vtbl_sigelem.svt_clear = coro_sigelem_clr; + { + /* + * we provide a vtbvl for %SIG magic that replaces PL_vtbl_sig + * by coro_sig_vtbl in hash values. + */ + MAGIC *mg = mg_find ((SV *)GvHV (gv_fetchpv ("SIG", GV_ADD | GV_NOTQUAL, SVt_PVHV)), PERL_MAGIC_sig); + + /* this only works if perl doesn't have a vtbl for %SIG */ + assert (!mg->mg_virtual); + + /* + * The irony is that the perl API itself asserts that mg_virtual + * must be non-const, yet perl5porters insisted on marking their + * vtbls as read-only, just to thwart perl modules from patching + * them. + */ + mg->mg_virtual = (MGVTBL *)&coro_sig_vtbl; + mg->mg_flags |= MGf_COPY; + + coro_sigelem_vtbl = PL_vtbl_sigelem; + coro_sigelem_vtbl.svt_get = coro_sigelem_get; + coro_sigelem_vtbl.svt_set = coro_sigelem_set; + coro_sigelem_vtbl.svt_clear = coro_sigelem_clr; + } rv_diehook = newRV_inc ((SV *)gv_fetchpv ("Coro::State::diehook" , 0, SVt_PVCV)); rv_warnhook = newRV_inc ((SV *)gv_fetchpv ("Coro::State::warnhook", 0, SVt_PVCV)); @@ -3920,22 +3972,50 @@ } void -swap_sv (Coro::State coro, SV *sv, SV *swapsv) +swap_sv (Coro::State coro, SV *sva, SV *svb) CODE: { struct coro *current = SvSTATE_current; + AV *swap_sv; + int i; + + sva = SvRV (sva); + svb = SvRV (svb); if (current == coro) - SWAP_SVS (current); + SWAP_SVS_LEAVE (current); if (!coro->swap_sv) coro->swap_sv = newAV (); - av_push (coro->swap_sv, SvREFCNT_inc_NN (SvRV (sv ))); - av_push (coro->swap_sv, SvREFCNT_inc_NN (SvRV (swapsv))); + swap_sv = coro->swap_sv; + + for (i = AvFILLp (swap_sv) - 1; i >= 0; i -= 2) + { + SV *a = AvARRAY (swap_sv)[i ]; + SV *b = AvARRAY (swap_sv)[i + 1]; + + if (a == sva && b == svb) + { + SvREFCNT_dec_NN (a); + SvREFCNT_dec_NN (b); + + for (; i <= AvFILLp (swap_sv) - 2; i++) + AvARRAY (swap_sv)[i] = AvARRAY (swap_sv)[i + 2]; + + AvFILLp (swap_sv) -= 2; + + goto removed; + } + } + + av_push (swap_sv, SvREFCNT_inc_NN (sva)); + av_push (swap_sv, SvREFCNT_inc_NN (svb)); + + removed: if (current == coro) - SWAP_SVS (current); + SWAP_SVS_ENTER (current); } @@ -4259,11 +4339,14 @@ RETVAL void -up (SV *self, int adjust = 1) - ALIAS: - adjust = 1 +up (SV *self) + CODE: + coro_semaphore_adjust (aTHX_ (AV *)SvRV (self), 1); + +void +adjust (SV *self, int adjust) CODE: - coro_semaphore_adjust (aTHX_ (AV *)SvRV (self), ix ? adjust : 1); + coro_semaphore_adjust (aTHX_ (AV *)SvRV (self), adjust); void down (...) diff -Nru libcoro-perl-6.490/Coro/Storable.pm libcoro-perl-6.511/Coro/Storable.pm --- libcoro-perl-6.490/Coro/Storable.pm 2015-10-16 23:42:40.000000000 +0000 +++ libcoro-perl-6.511/Coro/Storable.pm 2016-06-26 21:45:42.000000000 +0000 @@ -84,7 +84,7 @@ use Storable; use base "Exporter"; -our $VERSION = 6.49; +our $VERSION = 6.511; our @EXPORT = qw(thaw freeze nfreeze blocking_thaw blocking_freeze blocking_nfreeze); our $GRANULARITY = 0.01; diff -Nru libcoro-perl-6.490/Coro/Timer.pm libcoro-perl-6.511/Coro/Timer.pm --- libcoro-perl-6.490/Coro/Timer.pm 2015-10-16 23:42:40.000000000 +0000 +++ libcoro-perl-6.511/Coro/Timer.pm 2016-06-26 21:45:42.000000000 +0000 @@ -28,7 +28,7 @@ use Coro (); use Coro::AnyEvent (); -our $VERSION = 6.49; +our $VERSION = 6.511; our @EXPORT_OK = qw(timeout sleep); # compatibility with older programs diff -Nru libcoro-perl-6.490/Coro/Util.pm libcoro-perl-6.511/Coro/Util.pm --- libcoro-perl-6.490/Coro/Util.pm 2015-10-16 23:42:40.000000000 +0000 +++ libcoro-perl-6.511/Coro/Util.pm 2016-06-26 21:45:42.000000000 +0000 @@ -41,7 +41,7 @@ our @EXPORT = qw(gethostbyname gethostbyaddr); our @EXPORT_OK = qw(inet_aton fork_eval); -our $VERSION = 6.49; +our $VERSION = 6.511; our $MAXPARALLEL = 16; # max. number of parallel jobs diff -Nru libcoro-perl-6.490/Coro.pm libcoro-perl-6.511/Coro.pm --- libcoro-perl-6.490/Coro.pm 2015-10-16 23:42:40.000000000 +0000 +++ libcoro-perl-6.511/Coro.pm 2016-06-26 21:45:42.000000000 +0000 @@ -368,7 +368,7 @@ our $main; # main coro our $current; # current coro -our $VERSION = 6.49; +our $VERSION = 6.511; our @EXPORT = qw(async async_pool cede schedule terminate current unblock_sub rouse_cb rouse_wait); our %EXPORT_TAGS = ( @@ -500,12 +500,13 @@ which somehow defeats the purpose of pooling (but is fine in the exceptional case). -The priority will be reset to C<0> after each run, tracing will be -disabled, the description will be reset and the default output filehandle -gets restored, so you can change all these. Otherwise the coro will -be re-used "as-is": most notably if you change other per-coro global -stuff such as C<$/> you I revert that change, which is most -simply done by using local as in: C<< local $/ >>. +The priority will be reset to C<0> after each run, all C calls +will be undone, tracing will be disabled, the description will be reset +and the default output filehandle gets restored, so you can change all +these. Otherwise the coro will be re-used "as-is": most notably if you +change other per-coro global stuff such as C<$/> you I revert +that change, which is most simply done by using local as in: C<< local $/ +>>. The idle pool size is limited to C<8> idle coros (this can be adjusted by changing $Coro::POOL_SIZE), but there can be as many non-idle diff -Nru libcoro-perl-6.490/debian/changelog libcoro-perl-6.511/debian/changelog --- libcoro-perl-6.490/debian/changelog 2016-05-22 13:15:59.000000000 +0000 +++ libcoro-perl-6.511/debian/changelog 2016-09-25 21:17:12.000000000 +0000 @@ -1,3 +1,14 @@ +libcoro-perl (6.511-1) unstable; urgency=medium + + * New upstream release. + * Remove Jonathan Yu from Uploaders. Thanks for your work! + * Refresh spelling.patch. + * Drop coro-5.22.patch, issues are fixed upstream. + * Add back a hunk of the removed patch as coro-5.24.patch. + (Closes: #838851) + + -- gregor herrmann Sun, 25 Sep 2016 23:17:12 +0200 + libcoro-perl (6.490-1) unstable; urgency=medium * Team upload. diff -Nru libcoro-perl-6.490/debian/control libcoro-perl-6.511/debian/control --- libcoro-perl-6.490/debian/control 2016-05-22 13:02:32.000000000 +0000 +++ libcoro-perl-6.511/debian/control 2016-09-25 21:17:12.000000000 +0000 @@ -1,7 +1,6 @@ Source: libcoro-perl Maintainer: Debian Perl Group -Uploaders: Jonathan Yu , - gregor herrmann , +Uploaders: gregor herrmann , Krzysztof Krzyżaniak (eloy) , Alessandro Ghedini , Xavier Guimard diff -Nru libcoro-perl-6.490/debian/patches/coro-5.22.patch libcoro-perl-6.511/debian/patches/coro-5.22.patch --- libcoro-perl-6.490/debian/patches/coro-5.22.patch 2016-05-22 12:31:50.000000000 +0000 +++ libcoro-perl-6.511/debian/patches/coro-5.22.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,153 +0,0 @@ -Description: fix for Coro with 5.22 and 5.24 -Bug: https://rt.cpan.org/Public/Bug/Display.html?id=101063 -Bug-Debian: https://bugs.debian.org/787500 -Author: Anonymous -Origin: https://paste.debian.net/688072 -Last-Update: 2016-05-20 - ---- a/Coro/State.xs -+++ b/Coro/State.xs -@@ -39,6 +39,10 @@ - #ifdef PadARRAY - # define NEWPADAPI 1 - # define newPADLIST(var) (Newz (0, var, 1, PADLIST), Newx (PadlistARRAY (var), 2, PAD *)) -+# if PERL_VERSION_ATLEAST(5,22,0) && !PERL_VERSION_ATLEAST(5,24,0) -+# undef PadlistNAMES -+# define PadlistNAMES(pl) *((PADNAMELIST **)PadlistARRAY(pl)) -+# endif - #else - typedef AV PADNAMELIST; - # if !PERL_VERSION_ATLEAST(5,8,0) -@@ -951,7 +955,13 @@ coro_init_stacks (pTHX) - - New(54,PL_savestack,24,ANY); - PL_savestack_ix = 0; -+#ifdef SS_MAXPUSH -+ /* Of course, if you clone the code, you have to track the changes... */ -+ /*PL_savestack_max lies: it always has SS_MAXPUSH more than it claims */ -+ PL_savestack_max = 24 - SS_MAXPUSH; -+#else - PL_savestack_max = 24; -+#endif - - #if !PERL_VERSION_ATLEAST (5,10,0) - New(54,PL_retstack,4,OP*); -@@ -1029,10 +1039,6 @@ coro_rss (pTHX_ struct coro *coro) - - /** coroutine stack handling ************************************************/ - --static int (*orig_sigelem_get) (pTHX_ SV *sv, MAGIC *mg); --static int (*orig_sigelem_set) (pTHX_ SV *sv, MAGIC *mg); --static int (*orig_sigelem_clr) (pTHX_ SV *sv, MAGIC *mg); -- - /* apparently < 5.8.8 */ - #ifndef MgPV_nolen_const - #define MgPV_nolen_const(mg) (((((int)(mg)->mg_len)) == HEf_SVKEY) ? \ -@@ -1074,7 +1080,7 @@ coro_sigelem_get (pTHX_ SV *sv, MAGIC *m - } - } - -- return orig_sigelem_get ? orig_sigelem_get (aTHX_ sv, mg) : 0; -+ return PL_vtbl_sigelem.svt_get ? PL_vtbl_sigelem.svt_get (aTHX_ sv, mg) : 0; - } - - static int ecb_cold -@@ -1098,7 +1104,7 @@ coro_sigelem_clr (pTHX_ SV *sv, MAGIC *m - } - } - -- return orig_sigelem_clr ? orig_sigelem_clr (aTHX_ sv, mg) : 0; -+ return PL_vtbl_sigelem.svt_clear ? PL_vtbl_sigelem.svt_clear (aTHX_ sv, mg) : 0; - } - - static int ecb_cold -@@ -1122,9 +1128,42 @@ coro_sigelem_set (pTHX_ SV *sv, MAGIC *m - } - } - -- return orig_sigelem_set ? orig_sigelem_set (aTHX_ sv, mg) : 0; -+ return PL_vtbl_sigelem.svt_set ? PL_vtbl_sigelem.svt_set (aTHX_ sv, mg) : 0; -+} -+ -+static MGVTBL sigelem_vtbl = { -+ coro_sigelem_get, /* get */ -+ coro_sigelem_set, /* set */ -+ 0, /* len */ -+ coro_sigelem_clr, /* clear */ -+ 0, /* free */ -+ 0, /* copy */ -+ 0, /* dup */ -+#ifdef MGf_LOCAL -+ 0, /* local */ -+#endif -+}; -+ -+static int ecb_cold -+coro_sig_copy (pTHX_ SV *sv, MAGIC *mg, SV *nsv, const char *key, I32 klen) -+{ -+ sv_magicext (nsv, mg->mg_obj, 'u', &sigelem_vtbl, key, klen); -+ return 1; - } - -+static MGVTBL sig_vtbl = { -+ 0, /* get */ -+ 0, /* set */ -+ 0, /* len */ -+ 0, /* clear */ -+ 0, /* free */ -+ coro_sig_copy, /* copy */ -+ 0, /* dup */ -+#ifdef MGf_LOCAL -+ 0, /* local */ -+#endif -+}; -+ - static void - prepare_nop (pTHX_ struct coro_transfer_args *ta) - { -@@ -1395,7 +1434,11 @@ runops_trace (pTHX) - PUSHMARK (SP); - PUSHs (&PL_sv_yes); - PUSHs (fullname); -+# if PERL_VERSION_ATLEAST(5,24,0) -+ PUSHs (CxHASARGS (cx) ? sv_2mortal (newRV_inc (PL_curpad[0])) : &PL_sv_undef); -+#else - PUSHs (CxHASARGS (cx) ? sv_2mortal (newRV_inc ((SV *)cx->blk_sub.argarray)) : &PL_sv_undef); -+#endif - PUTBACK; - cb = hv_fetch ((HV *)SvRV (coro_current), "_trace_sub_cb", sizeof ("_trace_sub_cb") - 1, 0); - if (cb) call_sv (*cb, G_KEEPERR | G_EVAL | G_VOID | G_DISCARD); -@@ -1488,7 +1531,11 @@ transfer_tail (pTHX) - static void ecb_noinline ecb_cold - perlish_exit (pTHX) - { -- int exitstatus = perl_destruct (PL_curinterp); -+ int exitstatus; -+ /* Because we've skipped the "not essential" things, we've not popped all */ -+ /* the scopes, and perl_destruct has an assert() that checks this. */ -+ PL_scopestack_ix = 1; -+ exitstatus = perl_destruct (PL_curinterp); - perl_free (PL_curinterp); - exit (exitstatus); - } -@@ -3596,15 +3643,16 @@ BOOT: - DEFSV; - ERRSV; - -+ HV *sig = GvHV (gv_fetchpv ("SIG", GV_ADD|GV_NOTQUAL, SVt_PVHV)); -+ -+ sv_unmagic ((SV *)sig, PERL_MAGIC_sig); -+ sv_magicext ((SV *)sig, NULL, PERL_MAGIC_uvar, &sig_vtbl, NULL, 0)->mg_flags |= MGf_COPY; -+ - cctx_current = cctx_new_empty (); - - irsgv = gv_fetchpv ("/" , GV_ADD|GV_NOTQUAL, SVt_PV); - stdoutgv = gv_fetchpv ("STDOUT", GV_ADD|GV_NOTQUAL, SVt_PVIO); - -- orig_sigelem_get = PL_vtbl_sigelem.svt_get; PL_vtbl_sigelem.svt_get = coro_sigelem_get; -- orig_sigelem_set = PL_vtbl_sigelem.svt_set; PL_vtbl_sigelem.svt_set = coro_sigelem_set; -- orig_sigelem_clr = PL_vtbl_sigelem.svt_clear; PL_vtbl_sigelem.svt_clear = coro_sigelem_clr; -- - rv_diehook = newRV_inc ((SV *)gv_fetchpv ("Coro::State::diehook" , 0, SVt_PVCV)); - rv_warnhook = newRV_inc ((SV *)gv_fetchpv ("Coro::State::warnhook", 0, SVt_PVCV)); - diff -Nru libcoro-perl-6.490/debian/patches/coro-5.24.patch libcoro-perl-6.511/debian/patches/coro-5.24.patch --- libcoro-perl-6.490/debian/patches/coro-5.24.patch 1970-01-01 00:00:00.000000000 +0000 +++ libcoro-perl-6.511/debian/patches/coro-5.24.patch 2016-09-25 21:17:12.000000000 +0000 @@ -0,0 +1,21 @@ +Description: fix for Coro with 5.24 +Origin: https://paste.debian.net/688072 +Bug-Debian: https://bugs.debian.org/838851 +Bug: https://rt.cpan.org/Public/Bug/Display.html?id=114708 +Author: Anonymous +Last-Update: 2016-09-25 + +--- a/Coro/State.xs ++++ b/Coro/State.xs +@@ -1412,7 +1412,11 @@ + PUSHMARK (SP); + PUSHs (&PL_sv_yes); + PUSHs (fullname); ++# if PERL_VERSION_ATLEAST(5,24,0) ++ PUSHs (CxHASARGS (cx) ? sv_2mortal (newRV_inc (PL_curpad[0])) : &PL_sv_undef); ++#else + PUSHs (CxHASARGS (cx) ? sv_2mortal (newRV_inc ((SV *)cx->blk_sub.argarray)) : &PL_sv_undef); ++#endif + PUTBACK; + cb = hv_fetch ((HV *)SvRV (coro_current), "_trace_sub_cb", sizeof ("_trace_sub_cb") - 1, 0); + if (cb) call_sv (*cb, G_KEEPERR | G_EVAL | G_VOID | G_DISCARD); diff -Nru libcoro-perl-6.490/debian/patches/series libcoro-perl-6.511/debian/patches/series --- libcoro-perl-6.490/debian/patches/series 2016-05-22 12:31:50.000000000 +0000 +++ libcoro-perl-6.511/debian/patches/series 2016-09-25 21:17:12.000000000 +0000 @@ -2,4 +2,4 @@ whatis.patch spelling.patch fix-ftbfs-with-longjmp.patch -coro-5.22.patch +coro-5.24.patch diff -Nru libcoro-perl-6.490/debian/patches/spelling.patch libcoro-perl-6.511/debian/patches/spelling.patch --- libcoro-perl-6.490/debian/patches/spelling.patch 2016-05-22 12:31:50.000000000 +0000 +++ libcoro-perl-6.511/debian/patches/spelling.patch 2016-09-25 21:17:12.000000000 +0000 @@ -4,11 +4,11 @@ Forwarded: https://rt.cpan.org/Ticket/Display.html?id=82392 (not last version) Author: gregor herrmann Reviewed-by: Xavier Guimard -Last-Update: 2016-05-05 +Last-Update: 2016-07-20 --- a/Coro.pm +++ b/Coro.pm -@@ -639,7 +639,7 @@ +@@ -640,7 +640,7 @@ }; This can be used to localise about any resource (locale, uid, current @@ -17,7 +17,7 @@ coros. Another interesting example implements time-sliced multitasking using -@@ -755,7 +755,7 @@ +@@ -756,7 +756,7 @@ Returns true iff this Coro object is "new", i.e. has never been run yet. Those states basically consist of only the code reference to call and the arguments, but consumes very little other resources. New states will @@ -26,7 +26,7 @@ =item $state->is_zombie -@@ -1124,7 +1124,7 @@ +@@ -1125,7 +1125,7 @@ event-based program, or when you use event-based libraries. These typically register a callback for some event, and call that callback @@ -35,7 +35,7 @@ just wait for the event, simplyifying things. For example C<< AnyEvent->child >> registers a callback to be called when -@@ -1263,7 +1263,7 @@ +@@ -1264,7 +1264,7 @@ by the forks module, which gives you the (i-) threads API, just much faster). @@ -64,7 +64,7 @@ anymore, it's pushing up the daisies. =item $state->call ($coderef) -@@ -336,7 +336,7 @@ +@@ -346,7 +346,7 @@ =head3 METHODS FOR C CONTEXTS @@ -75,7 +75,7 @@ However. this is not always possible: For example, when Perl calls a C/XS function --- a/README +++ b/README -@@ -1037,7 +1037,7 @@ +@@ -1038,7 +1038,7 @@ evidenced by the forks module, which gives you the (i-) threads API, just much faster). @@ -139,7 +139,7 @@ C it (or vice versa), C can be called before C and so on: @@ -44,9 +44,9 @@ - our $VERSION = 6.49; + our $VERSION = 6.511; -=item new [inital count] +=item new [initial count] diff -Nru libcoro-perl-6.490/EV/EV.pm libcoro-perl-6.511/EV/EV.pm --- libcoro-perl-6.490/EV/EV.pm 2015-10-16 23:42:40.000000000 +0000 +++ libcoro-perl-6.511/EV/EV.pm 2016-06-26 21:45:42.000000000 +0000 @@ -60,7 +60,7 @@ use XSLoader; BEGIN { - our $VERSION = 6.49; + our $VERSION = 6.511; local $^W = 0; # avoid redefine warning for Coro::ready; XSLoader::load __PACKAGE__, $VERSION; diff -Nru libcoro-perl-6.490/Event/Event.pm libcoro-perl-6.511/Event/Event.pm --- libcoro-perl-6.490/Event/Event.pm 2015-10-16 23:42:40.000000000 +0000 +++ libcoro-perl-6.511/Event/Event.pm 2016-06-26 21:45:42.000000000 +0000 @@ -92,7 +92,7 @@ our @EXPORT = qw(loop unloop sweep); BEGIN { - our $VERSION = 6.49; + our $VERSION = 6.511; local $^W = 0; # avoid redefine warning for Coro::ready; XSLoader::load __PACKAGE__, $VERSION; diff -Nru libcoro-perl-6.490/META.json libcoro-perl-6.511/META.json --- libcoro-perl-6.490/META.json 2015-10-16 23:42:46.000000000 +0000 +++ libcoro-perl-6.511/META.json 2016-06-26 21:45:51.000000000 +0000 @@ -4,7 +4,7 @@ "unknown" ], "dynamic_config" : 1, - "generated_by" : "ExtUtils::MakeMaker version 7.0401, CPAN::Meta::Converter version 2.150001", + "generated_by" : "ExtUtils::MakeMaker version 7.1, CPAN::Meta::Converter version 2.150001", "license" : [ "unknown" ], @@ -51,5 +51,5 @@ } }, "release_status" : "stable", - "version" : 6.49 + "version" : 6.511 } diff -Nru libcoro-perl-6.490/META.yml libcoro-perl-6.511/META.yml --- libcoro-perl-6.490/META.yml 2015-10-16 23:42:46.000000000 +0000 +++ libcoro-perl-6.511/META.yml 2016-06-26 21:45:51.000000000 +0000 @@ -8,7 +8,7 @@ Canary::Stability: '0' ExtUtils::MakeMaker: '6.52' dynamic_config: 1 -generated_by: 'ExtUtils::MakeMaker version 7.0401, CPAN::Meta::Converter version 2.150001' +generated_by: 'ExtUtils::MakeMaker version 7.1, CPAN::Meta::Converter version 2.150001' license: unknown meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html @@ -32,4 +32,4 @@ Scalar::Util: '0' Storable: '2.15' common::sense: '0' -version: 6.49 +version: 6.511 diff -Nru libcoro-perl-6.490/README libcoro-perl-6.511/README --- libcoro-perl-6.490/README 2015-10-16 23:42:46.000000000 +0000 +++ libcoro-perl-6.511/README 2016-06-26 21:45:51.000000000 +0000 @@ -419,12 +419,13 @@ terminate or cancel, which somehow defeats the purpose of pooling (but is fine in the exceptional case). - The priority will be reset to 0 after each run, tracing will be - disabled, the description will be reset and the default output - filehandle gets restored, so you can change all these. Otherwise the - coro will be re-used "as-is": most notably if you change other - per-coro global stuff such as $/ you *must needs* revert that - change, which is most simply done by using local as in: "local $/". + The priority will be reset to 0 after each run, all "swap_sv" calls + will be undone, tracing will be disabled, the description will be + reset and the default output filehandle gets restored, so you can + change all these. Otherwise the coro will be re-used "as-is": most + notably if you change other per-coro global stuff such as $/ you + *must needs* revert that change, which is most simply done by using + local as in: "local $/". The idle pool size is limited to 8 idle coros (this can be adjusted by changing $Coro::POOL_SIZE), but there can be as many non-idle