: :#define addrA_reg %l0 :#define turn_reg %l1 :#define alive_reg %l2 :#define data_base_reg %l3 :#define my_id_reg %l4 :#define global_cnt_reg %l5 :#define prot_area_reg %l6 : :#define test_reg1 %i0 :#define test_reg2 %i1 :#define test_reg3 %i2 : :#define TIMEOUT 0x1000 :#define ITERATIONS 0x10 : :#include "hboot.s" : :.global main :main: : :th_fork(th_main,test_reg1) : $proc_num = 8; if(scalar(@ARGV)){ $proc_num = $ARGV[0]; if($proc_num >8){ :#define ITERATIONS 0x2 } } for ( $c = 0; $c < $proc_num; $c++ ){ $offs = 4 * $c; # threads own offset :th_main_${c}: : setx addrA, test_reg1, addrA_reg ! : setx alive, test_reg1, alive_reg ! : setx turn, test_reg1, turn_reg ! : setx prot_area, test_reg1, prot_area_reg ! : set ITERATIONS, global_cnt_reg : set ${c}, my_id_reg ! my ID : :getlock${c}: : set 1, test_reg1 ! store 1 into lock : st test_reg1, [alive_reg + ${offs}] ! alive flag : st test_reg1, [addrA_reg + ${offs}] ! : membar 0x40 ! IMPORTANT in TSO! : : mov %g0, test_reg2 for ( $k = 0; $k < ${proc_num} * 4; $k = $k + 4) { : ld [addrA_reg + ${k}], test_reg1 ! accumulate flags : add test_reg1, test_reg2, test_reg2 ! in test_reg2 } : : subcc test_reg2, 0x1, %g0 ! if result = 1 -> : be gotlock${c} ! got lock : nop : : st %g0, [addrA_reg + ${offs}] ! else release. : ! note alive stays on. : :wait_turn${c}: ! while not my turn : ld [turn_reg], test_reg3 ! read the turn reg. : subcc my_id_reg, test_reg3, %g0 ! and check : bne wait_turn${c} : nop : ! try to get lock again : ba getlock${c} : nop : :gotlock${c}: ! do something : set 1, test_reg1 ! store 1 in lock area : st test_reg1, [addrA_reg + ${offs}] ! : : ld [prot_area_reg], test_reg1 : inc test_reg1 : st test_reg1, [prot_area_reg] : : ld [prot_area_reg + 0xc], test_reg1 : inc test_reg1 : st test_reg1, [prot_area_reg + 0xc] : : ld [prot_area_reg + 0x10], test_reg1 : inc test_reg1 : st test_reg1, [prot_area_reg + 0x10] : : ld [prot_area_reg + 0x1c], test_reg1 : inc test_reg1 : st test_reg1, [prot_area_reg + 0x1c] : : ld [prot_area_reg + 0x20], test_reg1 : inc test_reg1 : st test_reg1, [prot_area_reg + 0x20] : :clearlock${c}: ! needs some work for($next = ($c+1) % ${proc_num}; $next != $c; $next = ($next+1) % ${proc_num}){ $tempoffs = 4 * $next; : mov ${next}, test_reg2 ! find next alive : ld [alive_reg + ${tempoffs}], test_reg1 : brnz test_reg1, foundnext${c} : nop } :foundnext${c}: : st test_reg2, [turn_reg] ! give it the turn : :check_done${c}: : deccc global_cnt_reg : be will_release${c} ! done : nop : st %g0, [addrA_reg + ${offs}] ! release : ba getlock${c} ! and iterate : nop :will_release${c}: : st %g0, [alive_reg + ${offs}] ! clear alive flag : st %g0, [addrA_reg + ${offs}] ! release... : ba good_end : nop : } :!--------------------------------------------------------------------- : :good_end: : ta T_GOOD_TRAP :bad_end: : ta T_BAD_TRAP : :!========================== : : :SECTION .MY_DATA0 TEXT_VA=0xf0100000, DATA_VA=0xd0100000 :attr_data { : Name = .MY_DATA0, : VA= 0x0d0100000 : RA= 0x1d0100000 : PA= ra2pa(0x1d0100000,0), : part_0_ctx_nonzero_tsb_config_0, : TTE_G=1, TTE_Context=0x44, TTE_V=1, TTE_Size=0, TTE_NFO=0, : TTE_IE=0, TTE_Soft2=0, TTE_Diag=0, TTE_Soft=0, : TTE_L=0, TTE_CP=1, TTE_CV=1, TTE_E=0, TTE_P=0, TTE_W=1 : } : :attr_text { : Name = .MY_DATA0, : VA= 0x0f0100000 : RA= 0x1f0100000 : PA= ra2pa(0x1f0100000,0), : part_0_ctx_nonzero_tsb_config_0, : TTE_G=1, TTE_Context=0x44, TTE_V=1, TTE_Size=0, TTE_NFO=0, : TTE_IE=0, TTE_Soft2=0, TTE_Diag=0, TTE_Soft=0, : TTE_L=0, TTE_CP=1, TTE_CV=1, TTE_E=0, TTE_P=0, TTE_W=1 : } : : .data : :.global addrA :.global turn :.align 0x4 :addrA: for ( $k = 0; $k < 32; $k++) { : .word 0x0 : .word 0x0 } : :.skip 0x1000 :.align 0x4 :turn: : .word 0x0 : .word 0x0 : .word 0x0 : :SECTION .MY_DATA1 TEXT_VA=0xf1110000, DATA_VA=0xd1110000 :attr_data { : Name = .MY_DATA1, : VA= 0x0d1110000, : RA= 0x1d1110000, : PA= ra2pa(0x1d1110000,0), : part_0_ctx_nonzero_tsb_config_0, : TTE_G=1, TTE_Context=0x44, TTE_V=1, TTE_Size=0, TTE_NFO=0, : TTE_IE=0, TTE_Soft2=0, TTE_Diag=0, TTE_Soft=0, : TTE_L=0, TTE_CP=1, TTE_CV=1, TTE_E=0, TTE_P=0, TTE_W=1 : } : :attr_text { : Name = .MY_DATA1, : VA= 0x0f1110000, : RA= 0x1f1110000, : PA= ra2pa(0x1f1110000,0), : part_0_ctx_nonzero_tsb_config_0, : TTE_G=1, TTE_Context=0x44, TTE_V=1, TTE_Size=0, TTE_NFO=0, : TTE_IE=0, TTE_Soft2=0, TTE_Diag=0, TTE_Soft=0, : TTE_L=0, TTE_CP=1, TTE_CV=1, TTE_E=0, TTE_P=0, TTE_W=1 : } : : .data :.global prot_area :prot_area: : .word 0xbeef : .skip 0x1000 : .word 0xbeef :.global alive :alive: : .word 0x0 : .word 0x0 : .word 0x0 : .word 0x0 : .word 0x0 : .word 0x0 : .word 0x0 : :.end