2 # Copyright (C) 2001-2008, Parrot Foundation.
7 use lib qw( . lib ../lib ../../lib );
14 t/pmc/threads.t - Threads
18 % prove t/pmc/threads.t
22 Tests running threads. All tests skipped unless running on known-good
27 if ( $^O eq "cygwin" ) {
28 my @uname = split / /, qx'uname -v';
30 if ( $uname[0] eq "2004-09-04" ) {
31 plan skip_all => "This cygwin version is known to fail the thread tests";
35 if ( $PConfig{HAS_THREADS} ) {
39 plan skip_all => "No threading enabled for '$^O'";
42 pasm_output_is( <<'CODE', <<'OUTPUT', "interp identity" );
49 new P4, ['ParrotThread']
60 # RT #46807 rework tests since we don't really have thread types?
63 skip 'busted on win32' => 2 if $^O eq 'MSWin32';
65 pir_output_is( <<'CODE', <<'OUTPUT', "thread type 1" );
70 threadfunc = get_global "foo"
71 thread = new ['ParrotThread']
72 thread.'run_clone'(threadfunc)
85 # check if vars are fresh
88 # print I5 # not done because registers aren't guaranteed to be
89 # initialized to anything in particular
91 set $I3, 0 # no retval
92 returncc # ret and be done with thread
94 # output from threads could be reversed
100 pir_output_is( <<'CODE', <<'OUTPUT', "thread type 1 -- repeated" );
110 .local pmc threadfunc
113 threadfunc = get_global "foo"
114 thread = new ['ParrotThread']
115 thread.'run_clone'(threadfunc)
128 # check if vars are fresh
131 # print I5 # not done because registers aren't guaranteed to be
132 # initialized to anything in particular
134 set $I3, 0 # no retval
135 returncc # ret and be done with thread
137 # output from threads could be reversed
147 pir_output_is( <<'CODE', <<'OUTPUT', "thread type 2" );
157 threadsub = get_global "foo"
158 thread = new ['ParrotThread']
159 thread.'run_clone'(threadsub, $P6)
160 sleep 1 # to let the thread run
171 passed = 'hello from'
173 # print I5 # not done because register initialization is not guaranteed
191 pir_output_is( <<'CODE', <<'OUTPUT', 'thread - kill' );
195 bounds 1 # assert slow core -S and -g are fine too
196 threadsub = get_global "foo"
197 thread = new ['ParrotThread']
202 thread.'run_clone'(threadsub)
204 sleep 1 # to let the thread run
225 pir_output_is( <<'CODE', <<'OUTPUT', "join, get retval" );
227 .const int MAX = 1000
230 Adder = get_global '_add'
231 kid = new ['ParrotThread']
233 from = new ['Integer']
238 kid.'run_clone'(Adder, Adder, from, to)
241 result = kid.'join'()
244 # sum = n * (n + 1)/2
246 Mul = new ['Integer']
261 sum = new ['Integer']
276 pir_output_is( <<'CODE', <<'OUT', "sub name lookup in new thread" );
278 $P0 = get_global ['Foo'], 'foo'
288 $P0 = new ['ParrotThread']
289 .local pmc thread_main
290 thread_main = get_global 'thread_main'
291 $P0.'run_clone'(thread_main)
292 $P0.'join'() # RT #46813
302 print "not reached\n"
309 pir_output_is( <<'CODE', <<'OUTPUT', "CLONE_CODE only" );
311 .namespace [ 'Test2' ]
316 .namespace [ 'Test3' ]
321 .namespace [ 'main' ]
323 .include 'errors.pasm'
329 test3 = get_hll_global ['Test3'], 'test3'
332 errorsoff .PARROT_ERRORS_GLOBALS_FLAG
333 test4 = get_global 'test4'
334 if null test4 goto okay
340 .include 'cloneflags.pasm'
345 test2 = get_hll_global ['Test2'], 'test2'
347 test4 = new ['Integer']
349 set_global 'test4', test4
352 thread = new ['ParrotThread']
353 .local pmc thread_func
354 thread_func = get_global 'thread_func'
355 $I0 = .PARROT_CLONE_CODE
356 thread.'run'($I0, thread_func, test2)
368 pir_output_is( <<'CODE', <<'OUTPUT', "CLONE_CODE | CLONE_GLOBALS" );
375 .param pmc shortlabel
376 if what == expect goto okay
392 .sub thread_test_func
393 $P0 = get_hll_global [ 'Bar' ], 'alpha'
394 'is'($P0, 1, 'Bar::alpha == 1', 'alpha')
396 sleep 0.2 # give enough time that the main thread might modify
397 # any shared Foo::beta can cause phantom errors
398 $P0 = get_global 'beta'
399 'is'($P0, 2, 'Foo::beta == 2 [accessed locally]', 'beta1')
401 $P0 = get_global 'beta'
402 'is'($P0, 5, 'Foo::beta == 5 [accessed locally after assignment]', 'beta2')
403 $P0 = get_hll_global [ 'Foo' ], 'beta'
404 'is'($P0, 5, 'Foo::beta == 5 [after assign; absolute]', 'beta3')
407 .namespace [ 'main' ]
410 $P0 = new ['Integer']
412 set_hll_global [ 'Bar' ], 'alpha', $P0
413 $P0 = new ['Integer']
415 set_hll_global [ 'Foo' ], 'beta', $P0
418 .include 'cloneflags.pasm'
423 thread = new ['ParrotThread']
424 .local pmc _thread_func
425 _thread_func = get_hll_global [ 'Foo' ], 'thread_test_func'
426 $I0 = .PARROT_CLONE_CODE
427 bor $I0, $I0, .PARROT_CLONE_GLOBALS
429 thread.'run'($I0, _thread_func)
430 $P0 = get_hll_global [ 'Foo' ], 'beta'
451 local $TODO = "vtable overrides aren't properly cloned RT # 46511";
453 pir_output_is( <<'CODE', <<'OUTPUT', "CLONE_CODE | CLONE_CLASSES; superclass not built-in" );
457 print "called Foo's foometh\n"
461 print "called Foo's barmeth\n"
467 print "called Bar's barmeth\n"
470 .sub get_string :vtable :method
474 .namespace [ 'main' ]
478 addattribute $P1, 'foo1'
479 addattribute $P1, 'foo2'
480 $P2 = subclass $P1, 'Bar'
481 addattribute $P2, 'bar1'
484 .sub thread_test_func
490 $I0 = isa $P0, 'Integer'
504 .include 'cloneflags.pasm'
509 thread = new ['ParrotThread']
510 .local pmc _thread_func
511 _thread_func = get_hll_global ['main'], 'thread_test_func'
512 $I0 = .PARROT_CLONE_CODE
513 bor $I0, $I0, .PARROT_CLONE_CLASSES
515 thread.'run'($I0, _thread_func)
538 pir_output_is( <<'CODE', <<'OUTPUT', "CLONE_CODE | CLONE_CLASSES; superclass built-in", todo => 'likely incorrect test');
542 print "called Foo's foometh\n"
546 print "called Foo's barmeth\n"
552 print "called Bar's barmeth\n"
555 .sub get_string :vtable :method
559 .namespace [ 'main' ]
562 $P0 = get_class 'Integer'
563 $P1 = subclass $P0, 'Foo'
564 addattribute $P1, 'foo1'
565 addattribute $P1, 'foo2'
566 $P2 = subclass $P1, 'Bar'
567 addattribute $P2, 'bar1'
570 .sub thread_test_func
576 $I0 = isa $P0, 'Integer'
590 .include 'cloneflags.pasm'
595 thread = new ['ParrotThread']
596 .local pmc _thread_func
597 _thread_func = get_global 'thread_test_func'
598 $I0 = .PARROT_CLONE_CODE
599 bor $I0, $I0, .PARROT_CLONE_CLASSES
601 thread.'run'($I0, _thread_func)
623 pir_output_is( <<'CODE', <<'OUTPUT', "CLONE_CODE | CLONE_GLOBALS| CLONE_HLL" );
626 $P0 = new ['Integer']
631 .include 'interpinfo.pasm'
634 if $P0 == 42 goto okay1
638 $P1 = get_root_namespace
642 if $P0 == 43 goto okay2
650 .include 'cloneflags.pasm'
655 setup = get_root_namespace
656 setup = setup['test']
658 setup = setup['setup']
663 thread = new ['ParrotThread']
664 flags = .PARROT_CLONE_CODE
665 bor flags, flags, .PARROT_CLONE_GLOBALS
666 bor flags, flags, .PARROT_CLONE_HLL
668 thread.'run'(flags, test)
684 if ( $ENV{TEST_PROG_ARGS} ) {
685 push @todo, ( todo => 'Broken with CGP' ) if $ENV{TEST_PROG_ARGS} =~ /--runcore=cgp/;
686 push @todo, ( todo => 'Broken with JIT' ) if $ENV{TEST_PROG_ARGS} =~ /--runcore=jit/;
687 push @todo, ( todo => 'Broken with switch core' ) if $ENV{TEST_PROG_ARGS} =~ /--runcore=switch/;
689 pir_output_unlike( <<'CODE', qr/not/, "globals + constant table subs issue", @todo );
692 .include 'interpinfo.pasm'
697 number = get_global 'test_num'
698 if what == expect goto okay
707 $P0 = interpinfo .INTERPINFO_CURRENT_CONT
710 if $I0 == 0 goto done
714 $P0 = $P0.'continuation'()
726 $P0 = new ['Integer']
728 set_global 'foo', $P0
732 $P0 = get_global 'foo'
733 $P1 = get_hll_global [ 'Foo' ], 'foo'
738 $P0 = new ['Integer']
740 set_global 'foo', $P0
745 $P0 = get_global '_check_sanity'
747 $P0 = get_hll_global [ 'Foo' ], '_check_sanity'
753 $P0 = get_global 'foo'
760 $P0 = get_global '_check_value'
762 $P0 = get_hll_global [ 'Foo' ], '_check_value'
767 .const 'Sub' c_setup = 'setup'
768 .const 'Sub' c_sanity = 'check_sanity'
769 .const 'Sub' c_mutate = 'mutate'
770 .const 'Sub' c_value = 'check_value'
773 g_setup = get_hll_global [ 'Foo' ], 'setup'
775 g_sanity = get_hll_global [ 'Foo' ], 'check_sanity'
777 g_mutate = get_hll_global [ 'Foo' ], 'mutate'
779 g_value = get_hll_global [ 'Foo' ], 'check_value'
807 $P0 = new ['Integer']
809 set_global 'test_num', $P0
811 .const 'Sub' _check = 'full_check'
814 $P0 = new ['ParrotThread']
815 $P0.'run_clone'(_check)
821 <<'CODE', <<'OUTPUT', "CLONE_CODE|CLONE_GLOBALS|CLONE_HLL|CLONE_LIBRARIES", todo => 'RT #41373' );
823 .loadlib 'perl_group'
825 .include 'interpinfo.pasm'
830 .param pmc passed_value
832 the_value = new ['PerlInt']
834 set_hll_global ['Foo'], 'x', the_value
835 $S0 = typeof passed_value
836 $S1 = typeof the_value
841 ns = get_namespace ['Foo']
842 $P0 = interpinfo .INTERPINFO_CURRENT_SUB
843 ns = $P0.'get_namespace'()
846 if $P0 == the_value goto okay
856 .include 'cloneflags.pasm'
861 thread = new ['ParrotThread']
862 flags = .PARROT_CLONE_CODE
863 bor flags, flags, .PARROT_CLONE_GLOBALS
864 bor flags, flags, .PARROT_CLONE_HLL
865 bor flags, flags, .PARROT_CLONE_LIBRARIES
868 passed = new ['PerlInt']
871 .local pmc thread_func
872 thread_func = get_global 'test'
874 thread.'run'(flags, thread_func, passed)
892 # cperl-indent-level: 4
895 # vim: expandtab shiftwidth=4: