xref: /openbsd-src/gnu/usr.bin/perl/dist/threads-shared/t/wait.t (revision b39c515898423c8d899e35282f4b395f7cad3298)
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