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']
60 # TT #1249: 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 .local pmc salutation
172 salutation = box 'hello from'
174 # print I5 # not done because register initialization is not guaranteed
192 pir_output_is( <<'CODE', <<'OUTPUT', 'thread - kill' );
196 bounds 1 # assert slow core -S and -g are fine too
197 threadsub = get_global "foo"
198 thread = new ['ParrotThread']
203 thread.'run_clone'(threadsub)
205 sleep 1 # to let the thread run
226 pir_output_is( <<'CODE', <<'OUTPUT', "join, get retval" );
228 .const int MAX = 1000
231 Adder = get_global '_add'
232 kid = new ['ParrotThread']
234 from = new ['Integer']
239 kid.'run_clone'(Adder, Adder, from, to)
242 result = kid.'join'()
245 # sum = n * (n + 1)/2
247 Mul = new ['Integer']
262 sum = new ['Integer']
277 pir_output_is( <<'CODE', <<'OUT', "sub name lookup in new thread" );
279 $P0 = get_global ['Foo'], 'foo'
289 $P0 = new ['ParrotThread']
290 .local pmc thread_main
291 thread_main = get_global 'thread_main'
292 $P0.'run_clone'(thread_main)
303 print "not reached\n"
310 pir_output_is( <<'CODE', <<'OUTPUT', "CLONE_CODE only" );
312 .namespace [ 'Test2' ]
317 .namespace [ 'Test3' ]
322 .namespace [ 'main' ]
324 .include 'errors.pasm'
330 test3 = get_hll_global ['Test3'], 'test3'
333 errorsoff .PARROT_ERRORS_GLOBALS_FLAG
334 test4 = get_global 'test4'
335 if null test4 goto okay
341 .include 'cloneflags.pasm'
346 test2 = get_hll_global ['Test2'], 'test2'
348 test4 = new ['Integer']
350 set_global 'test4', test4
353 thread = new ['ParrotThread']
354 .local pmc thread_func
355 thread_func = get_global 'thread_func'
356 $I0 = .PARROT_CLONE_CODE
357 thread.'run'($I0, thread_func, test2)
369 pir_output_is( <<'CODE', <<'OUTPUT', "CLONE_CODE | CLONE_GLOBALS" );
376 .param pmc shortlabel
377 if what == expect goto okay
393 .sub thread_test_func
394 $P0 = get_hll_global [ 'Bar' ], 'alpha'
395 'is'($P0, 1, 'Bar::alpha == 1', 'alpha')
397 sleep 0.2 # give enough time that the main thread might modify
398 # any shared Foo::beta can cause phantom errors
399 $P0 = get_global 'beta'
400 'is'($P0, 2, 'Foo::beta == 2 [accessed locally]', 'beta1')
402 $P0 = get_global 'beta'
403 'is'($P0, 5, 'Foo::beta == 5 [accessed locally after assignment]', 'beta2')
404 $P0 = get_hll_global [ 'Foo' ], 'beta'
405 'is'($P0, 5, 'Foo::beta == 5 [after assign; absolute]', 'beta3')
408 .namespace [ 'main' ]
411 $P0 = new ['Integer']
413 set_hll_global [ 'Bar' ], 'alpha', $P0
414 $P0 = new ['Integer']
416 set_hll_global [ 'Foo' ], 'beta', $P0
419 .include 'cloneflags.pasm'
424 thread = new ['ParrotThread']
425 .local pmc _thread_func
426 _thread_func = get_hll_global [ 'Foo' ], 'thread_test_func'
427 $I0 = .PARROT_CLONE_CODE
428 bor $I0, $I0, .PARROT_CLONE_GLOBALS
430 thread.'run'($I0, _thread_func)
431 $P0 = get_hll_global [ 'Foo' ], 'beta'
452 local $TODO = "vtable overrides aren't properly cloned TT # 1248";
454 pir_output_is( <<'CODE', <<'OUTPUT', "CLONE_CODE | CLONE_CLASSES; superclass not built-in" );
458 print "called Foo's foometh\n"
462 print "called Foo's barmeth\n"
468 print "called Bar's barmeth\n"
471 .sub get_string :vtable :method
475 .namespace [ 'main' ]
479 addattribute $P1, 'foo1'
480 addattribute $P1, 'foo2'
481 $P2 = subclass $P1, 'Bar'
482 addattribute $P2, 'bar1'
485 .sub thread_test_func
491 $I0 = isa $P0, 'Integer'
505 .include 'cloneflags.pasm'
510 thread = new ['ParrotThread']
511 .local pmc _thread_func
512 _thread_func = get_hll_global ['main'], 'thread_test_func'
513 $I0 = .PARROT_CLONE_CODE
514 bor $I0, $I0, .PARROT_CLONE_CLASSES
516 thread.'run'($I0, _thread_func)
539 pir_output_is( <<'CODE', <<'OUTPUT', "CLONE_CODE | CLONE_CLASSES; superclass built-in", todo => 'likely incorrect test TT 1248');
543 print "called Foo's foometh\n"
547 print "called Foo's barmeth\n"
553 print "called Bar's barmeth\n"
556 .sub get_string :vtable :method
560 .namespace [ 'main' ]
563 $P0 = get_class 'Integer'
564 $P1 = subclass $P0, 'Foo'
565 addattribute $P1, 'foo1'
566 addattribute $P1, 'foo2'
567 $P2 = subclass $P1, 'Bar'
568 addattribute $P2, 'bar1'
571 .sub thread_test_func
577 $I0 = isa $P0, 'Integer'
591 .include 'cloneflags.pasm'
596 thread = new ['ParrotThread']
597 .local pmc _thread_func
598 _thread_func = get_global 'thread_test_func'
599 $I0 = .PARROT_CLONE_CODE
600 bor $I0, $I0, .PARROT_CLONE_CLASSES
602 thread.'run'($I0, _thread_func)
624 pir_output_is( <<'CODE', <<'OUTPUT', "CLONE_CODE | CLONE_GLOBALS| CLONE_HLL" );
627 $P0 = new ['Integer']
632 .include 'interpinfo.pasm'
635 if $P0 == 42 goto okay1
639 $P1 = get_root_namespace
643 if $P0 == 43 goto okay2
651 .include 'cloneflags.pasm'
656 setup = get_root_namespace
657 setup = setup['test']
659 setup = setup['setup']
664 thread = new ['ParrotThread']
665 flags = .PARROT_CLONE_CODE
666 bor flags, flags, .PARROT_CLONE_GLOBALS
667 bor flags, flags, .PARROT_CLONE_HLL
669 thread.'run'(flags, test)
683 # Direct constant access to sub objects commented out, see TT #1120.
684 pir_output_unlike( <<'CODE', qr/not/, "globals + constant table subs issue");
687 .include 'interpinfo.pasm'
691 .param string desc :optional
692 .param int have_desc :opt_flag
694 unless have_desc goto diagnose
699 number = get_global 'test_num'
700 if what == expect goto okay
709 $P0 = interpinfo .INTERPINFO_CURRENT_CONT
712 if $I0 == 0 goto done
715 $P0 = $P0.'continuation'()
727 $P0 = new ['Integer']
729 set_global 'foo', $P0
734 $P0 = get_global 'foo'
735 $P1 = get_hll_global [ 'Foo' ], 'foo'
740 $P0 = new ['Integer']
742 set_global 'foo', $P0
746 # _check_sanity( 'direct call' )
747 $P0 = get_global '_check_sanity'
748 $P0( 'call from get_global' )
749 $P0 = get_hll_global [ 'Foo' ], '_check_sanity'
750 $P0( 'call from get_hll_global' )
755 $P0 = get_global 'foo'
761 # _check_value(value)
762 $P0 = get_global '_check_value'
764 $P0 = get_hll_global [ 'Foo' ], '_check_value'
769 # .const 'Sub' c_setup = 'setup'
770 # .const 'Sub' c_sanity = 'check_sanity'
771 # .const 'Sub' c_mutate = 'mutate'
772 # .const 'Sub' c_value = 'check_value'
775 c_setup = get_global 'setup'
777 c_sanity = get_global 'check_sanity'
779 c_mutate = get_global 'mutate'
781 c_value = get_global 'check_value'
784 g_setup = get_hll_global [ 'Foo' ], 'setup'
786 g_sanity = get_hll_global [ 'Foo' ], 'check_sanity'
788 g_mutate = get_hll_global [ 'Foo' ], 'mutate'
790 g_value = get_hll_global [ 'Foo' ], 'check_value'
818 $P0 = new ['Integer']
820 set_global 'test_num', $P0
822 .const 'Sub' _check = 'full_check'
825 $P0 = new ['ParrotThread']
826 $P0.'run_clone'(_check)
832 <<'CODE', <<'OUTPUT', 'CLONE_CODE|CLONE_GLOBALS|CLONE_HLL|CLONE_LIBRARIES - TT # 1250' );
835 .include 'interpinfo.pasm'
841 .param pmc passed_value
843 the_value = new ['Integer']
845 set_hll_global ['Foo'], 'x', the_value
846 $S0 = typeof passed_value
847 $S1 = typeof the_value
852 ns = get_namespace ['Foo']
853 $P0 = interpinfo .INTERPINFO_CURRENT_SUB
854 ns = $P0.'get_namespace'()
857 if $P0 == the_value goto okay
866 .include 'cloneflags.pasm'
871 thread = new ['ParrotThread']
872 flags = .PARROT_CLONE_CODE
873 bor flags, flags, .PARROT_CLONE_GLOBALS
874 bor flags, flags, .PARROT_CLONE_HLL
875 bor flags, flags, .PARROT_CLONE_LIBRARIES
881 .local pmc thread_func
882 thread_func = get_global 'test'
884 thread.'run'(flags, thread_func, passed)
902 # cperl-indent-level: 4
905 # vim: expandtab shiftwidth=4: