: :#define addrA_reg %l0 :#define turn_reg %l1 :#define data_base_reg %l2 :#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 %i3 : :#define TIMEOUT 0x1000 :#define ITERATIONS 0x10 : :#include "hboot.s" : :.global main :main: : : wr %g0, 0x4, %fprs ! make sure fef is 1 for FP ops. : th_fork(th_main,test_reg1) : $proc_num = 8; if(scalar(@ARGV)){ $proc_num = $ARGV[0]; } for ( $c = 0; $c < $proc_num; $c++ ){ $offs = 4 * $c; # thread's own offset :th_main_${c}: : setx addrA, test_reg1, addrA_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 ! store my ID : :claim${c}: : set 1, test_reg1 ! store 1 in lock area : st test_reg1, [addrA_reg + ${offs}] :giveturnaway${c}: ! That's the essence $next = ($c + 1) % ${proc_num}; : set ${next}, test_reg1 ! of peterson : st test_reg1, [turn_reg] : membar 0x40 ! IMPORTANT : :getlock${c}: : prefetch [turn_reg], #n_writes : prefetch [addrA_reg], #n_writes : prefetch [prot_area_reg], #n_writes : ld [turn_reg + 0x8], test_reg1 : sub test_reg1, 0x55, test_reg1 : brz test_reg1, good_end : nop : mov %g0, test_reg2 ! while flags are busy : ! AND turn is not mine : ! WAIT 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 is 1 flags : be gotlock${c} ! are not busy : nop : :wait_turn${c}: : ld [turn_reg], test_reg3 ! read the turn reg. : subcc my_id_reg, test_reg3, %g0 ! and check : bne getlock${c} : nop : :gotlock${c}: : ld [prot_area_reg], test_reg1 : inc test_reg1 : st test_reg1, [prot_area_reg] : ldd [prot_area_reg], %f0 ! FP noise. : !faddd %f0, %f0, %f2 : !fsubd %f2, %f0, %f0 : std %f0, [prot_area_reg] : : ld [prot_area_reg + 0xc], test_reg1 : inc test_reg1 : st test_reg1, [prot_area_reg + 0xc] : ldd [prot_area_reg], %f0 ! FP noise. : !faddd %f0, %f0, %f2 : !fsubd %f2, %f0, %f0 : std %f0, [prot_area_reg] : : ld [prot_area_reg + 0x10], test_reg1 : inc test_reg1 : st test_reg1, [prot_area_reg + 0x10] : ldd [prot_area_reg], %f0 ! FP noise. : !faddd %f0, %f0, %f2 : !fsubd %f2, %f0, %f0 : std %f0, [prot_area_reg] : : ld [prot_area_reg + 0x1c], test_reg1 : inc test_reg1 : st test_reg1, [prot_area_reg + 0x1c] : ldd [prot_area_reg], %f0 ! FP noise. : !faddd %f0, %f0, %f2 : !fsubd %f2, %f0, %f0 : std %f0, [prot_area_reg] : : ld [prot_area_reg + 0x20], test_reg1 : inc test_reg1 : st test_reg1, [prot_area_reg + 0x20] : ldd [prot_area_reg], %f0 ! FP noise. : !faddd %f0, %f0, %f2 : !fsubd %f2, %f0, %f0 : std %f0, [prot_area_reg] : :clearlock${c}: : st %g0, [addrA_reg + ${offs}] ! release... : set ${next}, test_reg1 : st test_reg1, [turn_reg] : if($c == $proc_num -1){ : deccc global_cnt_reg : bne claim${c} : nop : set 0x55, test_reg1 : st test_reg1, [turn_reg + 0x8] : ba good_end : nop } else{ : ba claim${c} : 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 : :.end