1b39c5158Smillertuse strict; 2b39c5158Smillertuse warnings; 3b39c5158Smillert 4b39c5158SmillertBEGIN { 5b39c5158Smillert use Config; 6b39c5158Smillert if (! $Config{'useithreads'}) { 7b39c5158Smillert print("1..0 # SKIP Perl not compiled with 'useithreads'\n"); 8b39c5158Smillert exit(0); 9b39c5158Smillert } 10b39c5158Smillert if ($^O eq 'hpux' && $Config{osvers} <= 10.20) { 11b39c5158Smillert print("1..0 # SKIP Broken under HP-UX 10.20\n"); 12b39c5158Smillert exit(0); 13b39c5158Smillert } 14898184e3Ssthen 1556d68f1eSafresh1 # https://lists.alioth.debian.org/pipermail/perl-maintainers/2011-June/002285.html 16898184e3Ssthen # There _is_ TLS support on m68k, but this stress test is overwhelming 17898184e3Ssthen # for the hardware 18898184e3Ssthen if ($^O eq 'linux' && $Config{archname} =~ /^m68k/) { 19898184e3Ssthen print("1..0 # Skip: m68k doesn't have enough oomph for these stress tests\n"); 20898184e3Ssthen exit(0); 21898184e3Ssthen } 22b39c5158Smillert} 23b39c5158Smillert 24b39c5158Smillertuse ExtUtils::testlib; 25b39c5158Smillert 26b39c5158SmillertBEGIN { 27b39c5158Smillert $| = 1; 28b39c5158Smillert print("1..1\n"); ### Number of tests that will be run ### 29b39c5158Smillert}; 30b39c5158Smillert 31b39c5158Smillertuse threads; 32b39c5158Smillertuse threads::shared; 33b39c5158Smillert 34b39c5158Smillert### Start of Testing ### 35b39c5158Smillert 36b39c5158Smillert##### 37b39c5158Smillert# 38b39c5158Smillert# Launches a bunch of threads which are then 39b39c5158Smillert# restricted to finishing in numerical order 40b39c5158Smillert# 41b39c5158Smillert##### 42b39c5158Smillert{ 43b39c5158Smillert my $cnt = 50; 44b39c5158Smillert 45e9ce3842Safresh1 # Depending on hardware and compiler options, the time for a busy loop can 46e9ce3842Safresh1 # by a factor of (at least) 40, so one size doesn't fit all. 47e9ce3842Safresh1 # For a fixed iteration count, on a particularly slow machine the timeout 48e9ce3842Safresh1 # can fire before all threads have had a realistic chance to complete, but 49e9ce3842Safresh1 # dropping the iteration count will cause fast machines to finish each 50e9ce3842Safresh1 # thread too quickly. 51e9ce3842Safresh1 # Fastest machine I tested can loop 20,000,000 times a second, slowest 52e9ce3842Safresh1 # 500,000 53e9ce3842Safresh1 54e9ce3842Safresh1 my $busycount; 55e9ce3842Safresh1 { 56e9ce3842Safresh1 my $tries = 1e4; 57e9ce3842Safresh1 # Try to align to the start of a second: 58e9ce3842Safresh1 my $want = time + 1; 59e9ce3842Safresh1 while (time < $want && --$tries) { 60e9ce3842Safresh1 my $sum; 61e9ce3842Safresh1 for (0..1e4) { 62e9ce3842Safresh1 ++$sum; 63e9ce3842Safresh1 } 64e9ce3842Safresh1 } 65e9ce3842Safresh1 66e9ce3842Safresh1 if ($tries) { 67e9ce3842Safresh1 $tries = 1e4; 68e9ce3842Safresh1 ++$want; 69e9ce3842Safresh1 70e9ce3842Safresh1 while (time < $want && --$tries) { 71e9ce3842Safresh1 my $sum; 72e9ce3842Safresh1 for (0..1e4) { 73e9ce3842Safresh1 ++$sum; 74e9ce3842Safresh1 } 75e9ce3842Safresh1 } 76e9ce3842Safresh1 77e9ce3842Safresh1 # This should be about 0.025s 78e9ce3842Safresh1 $busycount = (1e4 - $tries) * 250; 79e9ce3842Safresh1 } else { 80e9ce3842Safresh1 # Fall back to the old default if everything fails 81e9ce3842Safresh1 $busycount = 500000; 82e9ce3842Safresh1 } 83e9ce3842Safresh1 print "# Looping for $busycount iterations should take about 0.025s\n"; 84e9ce3842Safresh1 } 85e9ce3842Safresh1 86*fac98b93Safresh1 my $TIMEOUT = 600; 87b39c5158Smillert 88b39c5158Smillert my $mutex = 1; 89b39c5158Smillert share($mutex); 90b39c5158Smillert 91b39c5158Smillert my $warning; 92b39c5158Smillert $SIG{__WARN__} = sub { $warning = shift; }; 93b39c5158Smillert 94b39c5158Smillert my @threads; 95b39c5158Smillert 96b39c5158Smillert for (reverse(1..$cnt)) { 97b39c5158Smillert $threads[$_] = threads->create(sub { 98b39c5158Smillert my $tnum = shift; 99b39c5158Smillert my $timeout = time() + $TIMEOUT; 100b39c5158Smillert threads->yield(); 101b39c5158Smillert 102b39c5158Smillert # Randomize the amount of work the thread does 103b39c5158Smillert my $sum; 104e9ce3842Safresh1 for (0..($busycount+int(rand($busycount)))) { 105b39c5158Smillert $sum++ 106b39c5158Smillert } 107b39c5158Smillert 108b39c5158Smillert # Lock the mutex 109b39c5158Smillert lock($mutex); 110b39c5158Smillert 111b39c5158Smillert # Wait for my turn to finish 112b39c5158Smillert while ($mutex != $tnum) { 113b39c5158Smillert if (! cond_timedwait($mutex, $timeout)) { 114b39c5158Smillert if ($mutex == $tnum) { 115b39c5158Smillert return ('timed out - cond_broadcast not received'); 116b39c5158Smillert } else { 117b39c5158Smillert return ('timed out'); 118b39c5158Smillert } 119b39c5158Smillert } 120b39c5158Smillert } 121b39c5158Smillert 122b39c5158Smillert # Finish up 123b39c5158Smillert $mutex++; 124b39c5158Smillert cond_broadcast($mutex); 125b39c5158Smillert return ('okay'); 126b39c5158Smillert }, $_); 127b39c5158Smillert 128b39c5158Smillert # Handle thread creation failures 129b39c5158Smillert if ($warning) { 130b39c5158Smillert my $printit = 1; 131b39c5158Smillert if ($warning =~ /returned 11/) { 132b39c5158Smillert $warning = "Thread creation failed due to 'No more processes'\n"; 133b39c5158Smillert $printit = (! $ENV{'PERL_CORE'}); 134b39c5158Smillert } elsif ($warning =~ /returned 12/) { 135b39c5158Smillert $warning = "Thread creation failed due to 'No more memory'\n"; 136b39c5158Smillert $printit = (! $ENV{'PERL_CORE'}); 137b39c5158Smillert } 138b39c5158Smillert print(STDERR "# Warning: $warning") if ($printit); 139b39c5158Smillert lock($mutex); 140b39c5158Smillert $mutex = $_ + 1; 141b39c5158Smillert last; 142b39c5158Smillert } 143b39c5158Smillert } 144b39c5158Smillert 145b39c5158Smillert # Gather thread results 146b39c5158Smillert my ($okay, $failures, $timeouts, $unknown) = (0, 0, 0, 0, 0); 147b39c5158Smillert for (1..$cnt) { 148b39c5158Smillert if (! $threads[$_]) { 149b39c5158Smillert $failures++; 150b39c5158Smillert } else { 151b39c5158Smillert my $rc = $threads[$_]->join(); 152b39c5158Smillert if (! $rc) { 153b39c5158Smillert $failures++; 154b39c5158Smillert } elsif ($rc =~ /^timed out/) { 155b39c5158Smillert $timeouts++; 156b39c5158Smillert } elsif ($rc eq 'okay') { 157b39c5158Smillert $okay++; 158b39c5158Smillert } else { 159b39c5158Smillert $unknown++; 160b39c5158Smillert print(STDERR "# Unknown error: $rc\n"); 161b39c5158Smillert } 162b39c5158Smillert } 163b39c5158Smillert } 164b39c5158Smillert 165b39c5158Smillert if ($failures) { 166b39c5158Smillert my $only = $cnt - $failures; 167b39c5158Smillert print(STDERR "# Warning: Intended to use $cnt threads, but could only muster $only\n"); 168b39c5158Smillert $cnt -= $failures; 169b39c5158Smillert } 170b39c5158Smillert 171b39c5158Smillert if ($unknown || (($okay + $timeouts) != $cnt)) { 172b39c5158Smillert print("not ok 1\n"); 173b39c5158Smillert my $too_few = $cnt - ($okay + $timeouts + $unknown); 174b39c5158Smillert print(STDERR "# Test failed:\n"); 175b39c5158Smillert print(STDERR "#\t$too_few too few threads reported\n") if $too_few; 176b39c5158Smillert print(STDERR "#\t$unknown unknown errors\n") if $unknown; 177b39c5158Smillert print(STDERR "#\t$timeouts threads timed out\n") if $timeouts; 178b39c5158Smillert 179b39c5158Smillert } elsif ($timeouts) { 180b39c5158Smillert # Frequently fails under MSWin32 due to deadlocking bug in Windows 181b39c5158Smillert # hence test is TODO under MSWin32 18256d68f1eSafresh1 # https://rt.perl.org/rt3/Public/Bug/Display.html?id=41574 183b39c5158Smillert # http://support.microsoft.com/kb/175332 184b39c5158Smillert if ($^O eq 'MSWin32') { 185b39c5158Smillert print("not ok 1 # TODO - not reliable under MSWin32\n") 186b39c5158Smillert } else { 187b39c5158Smillert print("not ok 1\n"); 188b39c5158Smillert print(STDERR "# Test failed: $timeouts threads timed out\n"); 189b39c5158Smillert } 190b39c5158Smillert 191b39c5158Smillert } else { 192b39c5158Smillert print("ok 1\n"); 193b39c5158Smillert } 194b39c5158Smillert} 195b39c5158Smillert 196b39c5158Smillertexit(0); 197b39c5158Smillert 198b39c5158Smillert# EOF 199