第 1~3题:
.main
.top
sub $1,%dx
test $0,%dx
jgte .top
halt
loop.s内容大概就是一个空循环,dx每次减1,直到dx<0为止
1.输入如下命令:
./x86.py -p loop.s -t 1 -i 100 -R dx
得到
ARG seed 0
ARG numthreads 1
ARG program loop.s
ARG interrupt frequency 100
ARG interrupt randomness False
ARG argv
ARG load address 1000
ARG memsize 128
ARG memtrace
ARG regtrace dx
ARG cctrace False
ARG printstats False
ARG verbose False
dx Thread 0
?
? 1000 sub $1,%dx
? 1001 test $0,%dx
? 1002 jgte .top
? 1003 halt
zc@ubuntu:~/Downloads/Currency/HW-ThreadsIntro$
第一题就是解释dx在运行过程中的值
答:
没有显示的设置dx,值默认就是0,所以dx减1以后为-1,不满足大于等于零的循环条件,结束。
结果就是指令没执行前dx是0,之后全是-1
2.输入命令:
./x86.py -p loop.s -t 2 -i 100 -a dx=3,dx=3 -R dx
两个线程dx寄存器的值均初始化为3,循环4次结束,由于中断频率设置的是100条指令发生一次中断,所以这两个线程都一直执行到结束
如果将中断频率改的更小一点,线程执行过程中就会发生中断
但不会影响计算,线程发生调度的时候上下文被保存起来,dx的值被保存到TCB中,切换回自己的时候会将dx恢复。
3.将中断频率设置的非常小并且随机(-r),使用不同的种子观察交替
结果仍然是正确的
例:
./x86.py -p loop.s -t 2 -i 3 -a dx=3,dx=3 -r-R dx -s 3
运行结果如下
dx初始均为3,每次经过sub指令使dx值减1,可见计算过程是正确的
第4~8题
looping-race-nolock.s的功能是:
do{
R[ax] <-- [M]
R[ax] <-- R[ax] + 1
[M] <-- R[ax]
R[bx] <-- R[bx] - 1
}while( R[bx] > 0)
如果在 “取数 – 计算 --存数” 的过程中发生中断,其结果便很有可能出错
例:
./x86.py -p looping-race-nolock.s -t 2 -i 2 -r -s 0 -M 2000 -a bx = 3 -R bx -c
bx = 3, 地址为2000的内存存储的值为0,两个线程各循环3次,正确计算结果[2000]的值应该为6,实际结果是3,原因就是没有互斥访问临界区
第 9~10题
wait-for-me.s内容
.main
test $1, %ax # ax should be 1 (signaller) or 0 (waiter)
je .signaller
.waiter
mov 2000, %cx
test $1, %cx
jne .waiter
halt
.signaller
mov $1, 2000
halt
检查ax的值,
if ax = 1, 跳转到signaller 将地址为2000的内存设置为1
if ax = 0, 执行waiter 等待直到其他线程将地址为2000的内存值设置为1
第九题的结果如下
./x86.py -p wait-for-me.s -a ax=1,ax=0 -R ax -M 2000
线程0的ax初始化为1,执行signaller,将内存M设置为1
线程1的ax初始化为0,执行waiter,再判断M存储的值是否为1,由于线程0刚刚将[M]设置为1,所以循环结束
第十题
./x86.py -p wait-for-me.s -a ax=0,ax=1 -R ax -M 2000
线程0的ax值初始为0,线程1的ax初始为1,所以线程0会进入waiter一直循环,直到发生时钟中断(可以根据 -i xxx 设置中断的频率)转而执行线程1
线程1进入signaller将地址2000的内存值更改为1,结束,回到线程0,此时内存地址2000处的值已被修改,线程0的循环结束