1*b39c5158Smillertuse strict; 2*b39c5158Smillertuse warnings; 3*b39c5158Smillert 4*b39c5158SmillertBEGIN { 5*b39c5158Smillert # Import test.pl into its own package 6*b39c5158Smillert { 7*b39c5158Smillert package Test; 8*b39c5158Smillert require($ENV{PERL_CORE} ? '../../t/test.pl' : './t/test.pl'); 9*b39c5158Smillert } 10*b39c5158Smillert 11*b39c5158Smillert use Config; 12*b39c5158Smillert if (! $Config{'useithreads'}) { 13*b39c5158Smillert Test::skip_all(q/Perl not compiled with 'useithreads'/); 14*b39c5158Smillert } 15*b39c5158Smillert} 16*b39c5158Smillert 17*b39c5158Smillertuse ExtUtils::testlib; 18*b39c5158Smillert 19*b39c5158Smillertsub ok { 20*b39c5158Smillert my ($id, $ok, $name) = @_; 21*b39c5158Smillert 22*b39c5158Smillert # You have to do it this way or VMS will get confused. 23*b39c5158Smillert if ($ok) { 24*b39c5158Smillert print("ok $id - $name\n"); 25*b39c5158Smillert } else { 26*b39c5158Smillert print("not ok $id - $name\n"); 27*b39c5158Smillert printf("# Failed test at line %d\n", (caller)[2]); 28*b39c5158Smillert } 29*b39c5158Smillert 30*b39c5158Smillert return ($ok); 31*b39c5158Smillert} 32*b39c5158Smillert 33*b39c5158SmillertBEGIN { 34*b39c5158Smillert $| = 1; 35*b39c5158Smillert print("1..91\n"); ### Number of tests that will be run ### 36*b39c5158Smillert}; 37*b39c5158Smillert 38*b39c5158Smillertuse threads; 39*b39c5158Smillertuse threads::shared; 40*b39c5158Smillert 41*b39c5158SmillertTest::watchdog(300); # In case we get stuck 42*b39c5158Smillert 43*b39c5158Smillertmy $TEST = 1; 44*b39c5158Smillertok($TEST++, 1, 'Loaded'); 45*b39c5158Smillert 46*b39c5158Smillert### Start of Testing ### 47*b39c5158Smillert 48*b39c5158Smillert# cond_wait and cond_timedwait extended tests adapted from cond.t 49*b39c5158Smillert 50*b39c5158Smillert# The two skips later on in these tests refer to this quote from the 51*b39c5158Smillert# pod/perl583delta.pod: 52*b39c5158Smillert# 53*b39c5158Smillert# =head1 Platform Specific Problems 54*b39c5158Smillert# 55*b39c5158Smillert# The regression test ext/threads/shared/t/wait.t fails on early RedHat 9 56*b39c5158Smillert# and HP-UX 10.20 due to bugs in their threading implementations. 57*b39c5158Smillert# RedHat users should see https://rhn.redhat.com/errata/RHBA-2003-136.html 58*b39c5158Smillert# and consider upgrading their glibc. 59*b39c5158Smillert 60*b39c5158Smillert 61*b39c5158Smillert# - TEST basics 62*b39c5158Smillert 63*b39c5158Smillertok($TEST++, defined &cond_wait, "cond_wait() present"); 64*b39c5158Smillertok($TEST++, (prototype(\&cond_wait) eq '\[$@%];\[$@%]'), 65*b39c5158Smillert q/cond_wait() prototype '\[$@%];\[$@%]'/); 66*b39c5158Smillertok($TEST++, defined &cond_timedwait, "cond_timedwait() present"); 67*b39c5158Smillertok($TEST++, (prototype(\&cond_timedwait) eq '\[$@%]$;\[$@%]'), 68*b39c5158Smillert q/cond_timedwait() prototype '\[$@%]$;\[$@%]'/); 69*b39c5158Smillert 70*b39c5158Smillert 71*b39c5158Smillertmy @wait_how = ( 72*b39c5158Smillert "simple", # cond var == lock var; implicit lock; e.g.: cond_wait($c) 73*b39c5158Smillert "repeat", # cond var == lock var; explicit lock; e.g.: cond_wait($c, $c) 74*b39c5158Smillert "twain" # cond var != lock var; explicit lock; e.g.: cond_wait($c, $l) 75*b39c5158Smillert); 76*b39c5158Smillert 77*b39c5158Smillert 78*b39c5158SmillertSYNC_SHARED: { 79*b39c5158Smillert my $test_type :shared; # simple|repeat|twain 80*b39c5158Smillert 81*b39c5158Smillert my $cond :shared; 82*b39c5158Smillert my $lock :shared; 83*b39c5158Smillert 84*b39c5158Smillert ok($TEST++, 1, "Shared synchronization tests preparation"); 85*b39c5158Smillert 86*b39c5158Smillert sub signaller 87*b39c5158Smillert { 88*b39c5158Smillert my $testno = $_[0]; 89*b39c5158Smillert 90*b39c5158Smillert ok($testno++, 1, "$test_type: child before lock"); 91*b39c5158Smillert $test_type =~ /twain/ ? lock($lock) : lock($cond); 92*b39c5158Smillert ok($testno++, 1, "$test_type: child obtained lock"); 93*b39c5158Smillert 94*b39c5158Smillert if ($test_type =~ 'twain') { 95*b39c5158Smillert no warnings 'threads'; # lock var != cond var, so disable warnings 96*b39c5158Smillert cond_signal($cond); 97*b39c5158Smillert } else { 98*b39c5158Smillert cond_signal($cond); 99*b39c5158Smillert } 100*b39c5158Smillert ok($testno++, 1, "$test_type: child signalled condition"); 101*b39c5158Smillert 102*b39c5158Smillert return($testno); 103*b39c5158Smillert } 104*b39c5158Smillert 105*b39c5158Smillert # - TEST cond_wait 106*b39c5158Smillert 107*b39c5158Smillert sub cw 108*b39c5158Smillert { 109*b39c5158Smillert my ($testnum, $to) = @_; 110*b39c5158Smillert 111*b39c5158Smillert # Which lock to obtain? 112*b39c5158Smillert $test_type =~ /twain/ ? lock($lock) : lock($cond); 113*b39c5158Smillert ok($testnum++, 1, "$test_type: obtained initial lock"); 114*b39c5158Smillert 115*b39c5158Smillert my $thr = threads->create(\&signaller, $testnum); 116*b39c5158Smillert for ($test_type) { 117*b39c5158Smillert cond_wait($cond), last if /simple/; 118*b39c5158Smillert cond_wait($cond, $cond), last if /repeat/; 119*b39c5158Smillert cond_wait($cond, $lock), last if /twain/; 120*b39c5158Smillert die "$test_type: unknown test\n"; 121*b39c5158Smillert } 122*b39c5158Smillert $testnum = $thr->join(); 123*b39c5158Smillert ok($testnum++, 1, "$test_type: condition obtained"); 124*b39c5158Smillert 125*b39c5158Smillert return ($testnum); 126*b39c5158Smillert } 127*b39c5158Smillert 128*b39c5158Smillert foreach (@wait_how) { 129*b39c5158Smillert $test_type = "cond_wait [$_]"; 130*b39c5158Smillert my $thr = threads->create(\&cw, $TEST); 131*b39c5158Smillert $TEST = $thr->join(); 132*b39c5158Smillert } 133*b39c5158Smillert 134*b39c5158Smillert # - TEST cond_timedwait success 135*b39c5158Smillert 136*b39c5158Smillert sub ctw_ok 137*b39c5158Smillert { 138*b39c5158Smillert my ($testnum, $to) = @_; 139*b39c5158Smillert 140*b39c5158Smillert # Which lock to obtain? 141*b39c5158Smillert $test_type =~ /twain/ ? lock($lock) : lock($cond); 142*b39c5158Smillert ok($testnum++, 1, "$test_type: obtained initial lock"); 143*b39c5158Smillert 144*b39c5158Smillert my $thr = threads->create(\&signaller, $testnum); 145*b39c5158Smillert my $ok = 0; 146*b39c5158Smillert for ($test_type) { 147*b39c5158Smillert $ok = cond_timedwait($cond, time() + $to), last if /simple/; 148*b39c5158Smillert $ok = cond_timedwait($cond, time() + $to, $cond), last if /repeat/; 149*b39c5158Smillert $ok = cond_timedwait($cond, time() + $to, $lock), last if /twain/; 150*b39c5158Smillert die "$test_type: unknown test\n"; 151*b39c5158Smillert } 152*b39c5158Smillert $testnum = $thr->join(); 153*b39c5158Smillert ok($testnum++, $ok, "$test_type: condition obtained"); 154*b39c5158Smillert 155*b39c5158Smillert return ($testnum); 156*b39c5158Smillert } 157*b39c5158Smillert 158*b39c5158Smillert foreach (@wait_how) { 159*b39c5158Smillert $test_type = "cond_timedwait [$_]"; 160*b39c5158Smillert my $thr = threads->create(\&ctw_ok, $TEST, 5); 161*b39c5158Smillert $TEST = $thr->join(); 162*b39c5158Smillert } 163*b39c5158Smillert 164*b39c5158Smillert # - TEST cond_timedwait timeout 165*b39c5158Smillert 166*b39c5158Smillert sub ctw_fail 167*b39c5158Smillert { 168*b39c5158Smillert my ($testnum, $to) = @_; 169*b39c5158Smillert 170*b39c5158Smillert if ($^O eq "hpux" && $Config{osvers} <= 10.20) { 171*b39c5158Smillert # The lock obtaining would pass, but the wait will not. 172*b39c5158Smillert ok($testnum++, 1, "$test_type: obtained initial lock"); 173*b39c5158Smillert ok($testnum++, 0, "# SKIP see perl583delta"); 174*b39c5158Smillert 175*b39c5158Smillert } else { 176*b39c5158Smillert $test_type =~ /twain/ ? lock($lock) : lock($cond); 177*b39c5158Smillert ok($testnum++, 1, "$test_type: obtained initial lock"); 178*b39c5158Smillert my $ok; 179*b39c5158Smillert for ($test_type) { 180*b39c5158Smillert $ok = cond_timedwait($cond, time() + $to), last if /simple/; 181*b39c5158Smillert $ok = cond_timedwait($cond, time() + $to, $cond), last if /repeat/; 182*b39c5158Smillert $ok = cond_timedwait($cond, time() + $to, $lock), last if /twain/; 183*b39c5158Smillert die "$test_type: unknown test\n"; 184*b39c5158Smillert } 185*b39c5158Smillert ok($testnum++, ! defined($ok), "$test_type: timeout"); 186*b39c5158Smillert } 187*b39c5158Smillert 188*b39c5158Smillert return ($testnum); 189*b39c5158Smillert } 190*b39c5158Smillert 191*b39c5158Smillert foreach (@wait_how) { 192*b39c5158Smillert $test_type = "cond_timedwait pause, timeout [$_]"; 193*b39c5158Smillert my $thr = threads->create(\&ctw_fail, $TEST, 3); 194*b39c5158Smillert $TEST = $thr->join(); 195*b39c5158Smillert } 196*b39c5158Smillert 197*b39c5158Smillert foreach (@wait_how) { 198*b39c5158Smillert $test_type = "cond_timedwait instant timeout [$_]"; 199*b39c5158Smillert my $thr = threads->create(\&ctw_fail, $TEST, -60); 200*b39c5158Smillert $TEST = $thr->join(); 201*b39c5158Smillert } 202*b39c5158Smillert 203*b39c5158Smillert} # -- SYNCH_SHARED block 204*b39c5158Smillert 205*b39c5158Smillert 206*b39c5158Smillert# same as above, but with references to lock and cond vars 207*b39c5158Smillert 208*b39c5158SmillertSYNCH_REFS: { 209*b39c5158Smillert my $test_type :shared; # simple|repeat|twain 210*b39c5158Smillert 211*b39c5158Smillert my $true_cond :shared; 212*b39c5158Smillert my $true_lock :shared; 213*b39c5158Smillert 214*b39c5158Smillert my $cond = \$true_cond; 215*b39c5158Smillert my $lock = \$true_lock; 216*b39c5158Smillert 217*b39c5158Smillert ok($TEST++, 1, "Synchronization reference tests preparation"); 218*b39c5158Smillert 219*b39c5158Smillert sub signaller2 220*b39c5158Smillert { 221*b39c5158Smillert my $testno = $_[0]; 222*b39c5158Smillert 223*b39c5158Smillert ok($testno++, 1, "$test_type: child before lock"); 224*b39c5158Smillert $test_type =~ /twain/ ? lock($lock) : lock($cond); 225*b39c5158Smillert ok($testno++, 1, "$test_type: child obtained lock"); 226*b39c5158Smillert 227*b39c5158Smillert if ($test_type =~ 'twain') { 228*b39c5158Smillert no warnings 'threads'; # lock var != cond var, so disable warnings 229*b39c5158Smillert cond_signal($cond); 230*b39c5158Smillert } else { 231*b39c5158Smillert cond_signal($cond); 232*b39c5158Smillert } 233*b39c5158Smillert ok($testno++, 1, "$test_type: child signalled condition"); 234*b39c5158Smillert 235*b39c5158Smillert return($testno); 236*b39c5158Smillert } 237*b39c5158Smillert 238*b39c5158Smillert # - TEST cond_wait 239*b39c5158Smillert 240*b39c5158Smillert sub cw2 241*b39c5158Smillert { 242*b39c5158Smillert my ($testnum, $to) = @_; 243*b39c5158Smillert 244*b39c5158Smillert # Which lock to obtain? 245*b39c5158Smillert $test_type =~ /twain/ ? lock($lock) : lock($cond); 246*b39c5158Smillert ok($testnum++, 1, "$test_type: obtained initial lock"); 247*b39c5158Smillert 248*b39c5158Smillert my $thr = threads->create(\&signaller2, $testnum); 249*b39c5158Smillert for ($test_type) { 250*b39c5158Smillert cond_wait($cond), last if /simple/; 251*b39c5158Smillert cond_wait($cond, $cond), last if /repeat/; 252*b39c5158Smillert cond_wait($cond, $lock), last if /twain/; 253*b39c5158Smillert die "$test_type: unknown test\n"; 254*b39c5158Smillert } 255*b39c5158Smillert $testnum = $thr->join(); 256*b39c5158Smillert ok($testnum++, 1, "$test_type: condition obtained"); 257*b39c5158Smillert 258*b39c5158Smillert return ($testnum); 259*b39c5158Smillert } 260*b39c5158Smillert 261*b39c5158Smillert foreach (@wait_how) { 262*b39c5158Smillert $test_type = "cond_wait [$_]"; 263*b39c5158Smillert my $thr = threads->create(\&cw2, $TEST); 264*b39c5158Smillert $TEST = $thr->join(); 265*b39c5158Smillert } 266*b39c5158Smillert 267*b39c5158Smillert # - TEST cond_timedwait success 268*b39c5158Smillert 269*b39c5158Smillert sub ctw_ok2 270*b39c5158Smillert { 271*b39c5158Smillert my ($testnum, $to) = @_; 272*b39c5158Smillert 273*b39c5158Smillert # Which lock to obtain? 274*b39c5158Smillert $test_type =~ /twain/ ? lock($lock) : lock($cond); 275*b39c5158Smillert ok($testnum++, 1, "$test_type: obtained initial lock"); 276*b39c5158Smillert 277*b39c5158Smillert my $thr = threads->create(\&signaller2, $testnum); 278*b39c5158Smillert my $ok = 0; 279*b39c5158Smillert for ($test_type) { 280*b39c5158Smillert $ok = cond_timedwait($cond, time() + $to), last if /simple/; 281*b39c5158Smillert $ok = cond_timedwait($cond, time() + $to, $cond), last if /repeat/; 282*b39c5158Smillert $ok = cond_timedwait($cond, time() + $to, $lock), last if /twain/; 283*b39c5158Smillert die "$test_type: unknown test\n"; 284*b39c5158Smillert } 285*b39c5158Smillert $testnum = $thr->join(); 286*b39c5158Smillert ok($testnum++, $ok, "$test_type: condition obtained"); 287*b39c5158Smillert 288*b39c5158Smillert return ($testnum); 289*b39c5158Smillert } 290*b39c5158Smillert 291*b39c5158Smillert foreach (@wait_how) { 292*b39c5158Smillert $test_type = "cond_timedwait [$_]"; 293*b39c5158Smillert my $thr = threads->create(\&ctw_ok2, $TEST, 5); 294*b39c5158Smillert $TEST = $thr->join(); 295*b39c5158Smillert } 296*b39c5158Smillert 297*b39c5158Smillert # - TEST cond_timedwait timeout 298*b39c5158Smillert 299*b39c5158Smillert sub ctw_fail2 300*b39c5158Smillert { 301*b39c5158Smillert my ($testnum, $to) = @_; 302*b39c5158Smillert 303*b39c5158Smillert if ($^O eq "hpux" && $Config{osvers} <= 10.20) { 304*b39c5158Smillert # The lock obtaining would pass, but the wait will not. 305*b39c5158Smillert ok($testnum++, 1, "$test_type: obtained initial lock"); 306*b39c5158Smillert ok($testnum++, 0, "# SKIP see perl583delta"); 307*b39c5158Smillert 308*b39c5158Smillert } else { 309*b39c5158Smillert $test_type =~ /twain/ ? lock($lock) : lock($cond); 310*b39c5158Smillert ok($testnum++, 1, "$test_type: obtained initial lock"); 311*b39c5158Smillert my $ok; 312*b39c5158Smillert for ($test_type) { 313*b39c5158Smillert $ok = cond_timedwait($cond, time() + $to), last if /simple/; 314*b39c5158Smillert $ok = cond_timedwait($cond, time() + $to, $cond), last if /repeat/; 315*b39c5158Smillert $ok = cond_timedwait($cond, time() + $to, $lock), last if /twain/; 316*b39c5158Smillert die "$test_type: unknown test\n"; 317*b39c5158Smillert } 318*b39c5158Smillert ok($testnum++, ! defined($ok), "$test_type: timeout"); 319*b39c5158Smillert } 320*b39c5158Smillert 321*b39c5158Smillert return ($testnum); 322*b39c5158Smillert } 323*b39c5158Smillert 324*b39c5158Smillert foreach (@wait_how) { 325*b39c5158Smillert $test_type = "cond_timedwait pause, timeout [$_]"; 326*b39c5158Smillert my $thr = threads->create(\&ctw_fail2, $TEST, 3); 327*b39c5158Smillert $TEST = $thr->join(); 328*b39c5158Smillert } 329*b39c5158Smillert 330*b39c5158Smillert foreach (@wait_how) { 331*b39c5158Smillert $test_type = "cond_timedwait instant timeout [$_]"; 332*b39c5158Smillert my $thr = threads->create(\&ctw_fail2, $TEST, -60); 333*b39c5158Smillert $TEST = $thr->join(); 334*b39c5158Smillert } 335*b39c5158Smillert 336*b39c5158Smillert} # -- SYNCH_REFS block 337*b39c5158Smillert 338*b39c5158Smillert# Done 339*b39c5158Smillertexit(0); 340*b39c5158Smillert 341*b39c5158Smillert# EOF 342