2 # Copyright (C) 2001-2009, 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']
61 skip 'busted on win32' => 2 if $^O eq 'MSWin32';
63 pir_output_is( <<'CODE', <<'OUTPUT', "thread type 1" );
68 threadfunc = get_global "foo"
69 thread = new ['ParrotThread']
70 thread.'run_clone'(threadfunc)
83 # check if vars are fresh
86 # print I5 # not done because registers aren't guaranteed to be
87 # initialized to anything in particular
89 set $I3, 0 # no retval
90 returncc # ret and be done with thread
92 # output from threads could be reversed
98 pir_output_is( <<'CODE', <<'OUTPUT', "thread type 1 -- repeated" );
108 .local pmc threadfunc
111 threadfunc = get_global "foo"
112 thread = new ['ParrotThread']
113 thread.'run_clone'(threadfunc)
126 # check if vars are fresh
129 # print I5 # not done because registers aren't guaranteed to be
130 # initialized to anything in particular
132 set $I3, 0 # no retval
133 returncc # ret and be done with thread
135 # output from threads could be reversed
145 pir_output_is( <<'CODE', <<'OUTPUT', "thread type 2" );
155 threadsub = get_global "foo"
156 thread = new ['ParrotThread']
157 thread.'run_clone'(threadsub, $P6)
158 sleep 1 # to let the thread run
169 .local pmc salutation
170 salutation = box 'hello from'
172 # print I5 # not done because register initialization is not guaranteed
185 ThreadInterpreter tid 1
190 pir_output_is( <<'CODE', <<'OUTPUT', 'thread - kill' );
194 bounds 1 # assert slow core -S and -g are fine too
195 threadsub = get_global "foo"
196 thread = new ['ParrotThread']
201 thread.'run_clone'(threadsub)
203 sleep 1 # to let the thread run
224 pir_output_is( <<'CODE', <<'OUTPUT', "join, get retval" );
226 .const int MAX = 1000
229 Adder = get_global '_add'
230 kid = new ['ParrotThread']
232 from = new ['Integer']
237 kid.'run_clone'(Adder, Adder, from, to)
240 result = kid.'join'()
243 # sum = n * (n + 1)/2
245 Mul = new ['Integer']
260 sum = new ['Integer']
275 pir_output_is( <<'CODE', <<'OUT', "sub name lookup in new thread" );
277 $P0 = get_global ['Foo'], 'foo'
287 $P0 = new ['ParrotThread']
288 .local pmc thread_main
289 thread_main = get_global 'thread_main'
290 $P0.'run_clone'(thread_main)
301 print "not reached\n"
308 pir_output_is( <<'CODE', <<'OUTPUT', "CLONE_CODE only" );
310 .namespace [ 'Test2' ]
315 .namespace [ 'Test3' ]
320 .namespace [ 'main' ]
322 .include 'errors.pasm'
328 test3 = get_hll_global ['Test3'], 'test3'
331 errorsoff .PARROT_ERRORS_GLOBALS_FLAG
332 test4 = get_global 'test4'
333 if null test4 goto okay
339 .include 'cloneflags.pasm'
344 test2 = get_hll_global ['Test2'], 'test2'
346 test4 = new ['Integer']
348 set_global 'test4', test4
351 thread = new ['ParrotThread']
352 .local pmc thread_func
353 thread_func = get_global 'thread_func'
354 $I0 = .PARROT_CLONE_CODE
355 thread.'run'($I0, thread_func, test2)
367 pir_output_is( <<'CODE', <<'OUTPUT', "CLONE_CODE | CLONE_GLOBALS" );
374 .param pmc shortlabel
375 if what == expect goto okay
391 .sub thread_test_func
392 $P0 = get_hll_global [ 'Bar' ], 'alpha'
393 'is'($P0, 1, 'Bar::alpha == 1', 'alpha')
395 sleep 0.2 # give enough time that the main thread might modify
396 # any shared Foo::beta can cause phantom errors
397 $P0 = get_global 'beta'
398 'is'($P0, 2, 'Foo::beta == 2 [accessed locally]', 'beta1')
400 $P0 = get_global 'beta'
401 'is'($P0, 5, 'Foo::beta == 5 [accessed locally after assignment]', 'beta2')
402 $P0 = get_hll_global [ 'Foo' ], 'beta'
403 'is'($P0, 5, 'Foo::beta == 5 [after assign; absolute]', 'beta3')
406 .namespace [ 'main' ]
409 $P0 = new ['Integer']
411 set_hll_global [ 'Bar' ], 'alpha', $P0
412 $P0 = new ['Integer']
414 set_hll_global [ 'Foo' ], 'beta', $P0
417 .include 'cloneflags.pasm'
422 thread = new ['ParrotThread']
423 .local pmc _thread_func
424 _thread_func = get_hll_global [ 'Foo' ], 'thread_test_func'
425 $I0 = .PARROT_CLONE_CODE
426 bor $I0, $I0, .PARROT_CLONE_GLOBALS
428 thread.'run'($I0, _thread_func)
429 $P0 = get_hll_global [ 'Foo' ], 'beta'
450 local $TODO = "vtable overrides aren't properly cloned TT # 1248";
452 pir_output_is( <<'CODE', <<'OUTPUT', "CLONE_CODE | CLONE_CLASSES; superclass not built-in" );
456 print "called Foo's foometh\n"
460 print "called Foo's barmeth\n"
466 print "called Bar's barmeth\n"
469 .sub get_string :vtable :method
473 .namespace [ 'main' ]
477 addattribute $P1, 'foo1'
478 addattribute $P1, 'foo2'
479 $P2 = subclass $P1, 'Bar'
480 addattribute $P2, 'bar1'
483 .sub thread_test_func
489 $I0 = isa $P0, 'Integer'
503 .include 'cloneflags.pasm'
508 thread = new ['ParrotThread']
509 .local pmc _thread_func
510 _thread_func = get_hll_global ['main'], 'thread_test_func'
511 $I0 = .PARROT_CLONE_CODE
512 bor $I0, $I0, .PARROT_CLONE_CLASSES
514 thread.'run'($I0, _thread_func)
537 pir_output_is( <<'CODE', <<'OUTPUT', "CLONE_CODE | CLONE_CLASSES; superclass built-in", todo => 'likely incorrect test TT 1248');
541 print "called Foo's foometh\n"
545 print "called Foo's barmeth\n"
551 print "called Bar's barmeth\n"
554 .sub get_string :vtable :method
558 .namespace [ 'main' ]
561 $P0 = get_class 'Integer'
562 $P1 = subclass $P0, 'Foo'
563 addattribute $P1, 'foo1'
564 addattribute $P1, 'foo2'
565 $P2 = subclass $P1, 'Bar'
566 addattribute $P2, 'bar1'
569 .sub thread_test_func
575 $I0 = isa $P0, 'Integer'
589 .include 'cloneflags.pasm'
594 thread = new ['ParrotThread']
595 .local pmc _thread_func
596 _thread_func = get_global 'thread_test_func'
597 $I0 = .PARROT_CLONE_CODE
598 bor $I0, $I0, .PARROT_CLONE_CLASSES
600 thread.'run'($I0, _thread_func)
622 pir_output_is( <<'CODE', <<'OUTPUT', "CLONE_CODE | CLONE_GLOBALS| CLONE_HLL" );
625 $P0 = new ['Integer']
630 .include 'interpinfo.pasm'
633 if $P0 == 42 goto okay1
637 $P1 = get_root_namespace
641 if $P0 == 43 goto okay2
649 .include 'cloneflags.pasm'
654 setup = get_root_namespace
655 setup = setup['test']
657 setup = setup['setup']
662 thread = new ['ParrotThread']
663 flags = .PARROT_CLONE_CODE
664 bor flags, flags, .PARROT_CLONE_GLOBALS
665 bor flags, flags, .PARROT_CLONE_HLL
667 thread.'run'(flags, test)
681 # Direct constant access to sub objects commented out, see TT #1120.
682 pir_output_unlike( <<'CODE', qr/not/, "globals + constant table subs issue");
685 .include 'interpinfo.pasm'
689 .param string desc :optional
690 .param int have_desc :opt_flag
692 unless have_desc goto diagnose
697 number = get_global 'test_num'
698 if what == expect goto okay
707 $P0 = interpinfo .INTERPINFO_CURRENT_CONT
710 if $I0 == 0 goto done
713 $P0 = $P0.'continuation'()
725 $P0 = new ['Integer']
727 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
744 # _check_sanity( 'direct call' )
745 $P0 = get_global '_check_sanity'
746 $P0( 'call from get_global' )
747 $P0 = get_hll_global [ 'Foo' ], '_check_sanity'
748 $P0( 'call from get_hll_global' )
753 $P0 = get_global 'foo'
759 # _check_value(value)
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 c_setup = get_global 'setup'
775 c_sanity = get_global 'check_sanity'
777 c_mutate = get_global 'mutate'
779 c_value = get_global 'check_value'
782 g_setup = get_hll_global [ 'Foo' ], 'setup'
784 g_sanity = get_hll_global [ 'Foo' ], 'check_sanity'
786 g_mutate = get_hll_global [ 'Foo' ], 'mutate'
788 g_value = get_hll_global [ 'Foo' ], 'check_value'
816 $P0 = new ['Integer']
818 set_global 'test_num', $P0
820 .const 'Sub' _check = 'full_check'
823 $P0 = new ['ParrotThread']
824 $P0.'run_clone'(_check)
830 <<'CODE', <<'OUTPUT', 'CLONE_CODE|CLONE_GLOBALS|CLONE_HLL|CLONE_LIBRARIES - TT # 1250' );
833 .include 'interpinfo.pasm'
838 .param pmc passed_value
840 the_value = new ['Integer']
842 set_hll_global ['Foo'], 'x', the_value
843 $S0 = typeof passed_value
844 $S1 = typeof the_value
849 ns = get_namespace ['Foo']
850 $P0 = interpinfo .INTERPINFO_CURRENT_SUB
851 ns = $P0.'get_namespace'()
854 if $P0 == the_value goto okay
863 .include 'cloneflags.pasm'
868 thread = new ['ParrotThread']
869 flags = .PARROT_CLONE_CODE
870 bor flags, flags, .PARROT_CLONE_GLOBALS
871 bor flags, flags, .PARROT_CLONE_HLL
872 bor flags, flags, .PARROT_CLONE_LIBRARIES
878 .local pmc thread_func
879 thread_func = get_global 'test'
881 thread.'run'(flags, thread_func, passed)
899 # cperl-indent-level: 4
902 # vim: expandtab shiftwidth=4: