《操作系统》的实验代码。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

227 lines
8.0 KiB

  1. # lab7 理解race condition
  2. ## x86模拟运行环境
  3. x86.py是一个模拟执行基于汇编代码的多线程执行过程的模拟器。这里的汇编语法是基于很简单的x86汇编语法。
  4. 且没有包括OS的调度、context切换和中断处理过程。每条指令大小为一个byte。每个变量占4个byte
  5. 在硬件上模拟了4个通用寄存器:
  6. ```
  7. %ax, %bx, %cx, %dx
  8. ```
  9. 一个程序计数器`pc`,一个堆栈寄存器`sp`,和一小部分指令:
  10. ```
  11. mov immediate, register # immediate value --> register
  12. mov memory, register # memory --> register
  13. mov register, register # register --> register
  14. mov register, memory # register --> memory
  15. mov immediate, memory # immediate value --> memory
  16. add immediate, register # register = register + immediate
  17. add register1, register2 # register2 = register2 + register1
  18. sub immediate, register # register = register - immediate
  19. sub register1, register2 # register2 = register2 - register1
  20. test immediate, register # compare immediate and register (set condition codes)
  21. test register, immediate # compare register and immediate (set condition codes)
  22. test register, register # compare register and register (set condition codes)
  23. jne # jump if test'd values are not equal
  24. je # jump if test'd values are equal
  25. jlt # jump if test'd second is less than first
  26. jlte # jump if test'd second is less than or equal first
  27. jgt # jump if test'd second is greater than first
  28. jgte # jump if test'd second is greater than or equal first
  29. xchg register, memory # atomic exchange:
  30. # put value of register into memory
  31. # return old contents of memory into reg
  32. # do both things atomically
  33. nop # no op
  34. halt # stop
  35. push memory or register # push value in memory or from reg onto stack
  36. # stack is defined by sp register
  37. pop [register] # pop value off stack (into optional register)
  38. call label # call function at label
  39. yield # switch to the next thread in the runqueue
  40. ```
  41. 注意:
  42. - 'immediate' 格式是 $number
  43. - 'memory' 格式是 'number' 或 '(reg)' 或 'number(reg)' 或 'number(reg,reg)'
  44. - (%cx) -> 在括号中的register cx 的值 形成 address
  45. - 2000 -> 2000 形成 address
  46. - 1000(%dx) -> 1000 + dx的值 形成 address
  47. - 10(%ax,%bx) -> 10 + ax的值 + bx的值 形成 address
  48. - 'register' 格式是 %ax, %bx, %cx, %dx
  49. 下面是一个代码片段:
  50. ```
  51. .main
  52. mov 2000, %ax # 取地址2000处的内存单元的内容,并赋值给ax
  53. add $1, %ax # ax=ax+1
  54. mov %ax, 2000 # 把ax的内容存储到地址2000处的内存单元中
  55. halt
  56. ```
  57. 其含义如下
  58. ```
  59. 2000 -> 2000 形成地址 address
  60. (%cx) -> cx的内容 形成地址 address
  61. 1000(%dx) -> (1000+dx) 形成地址 address
  62. 10(%ax,%bx) -> (10+ax+bx) 形成地址 address
  63. halt -> 执行结束
  64. ```
  65. 循环执行的小例子片段
  66. ```
  67. .main
  68. .top
  69. sub $1,%dx
  70. test $0,%dx
  71. jgte .top
  72. halt
  73. ```
  74. x86.py模拟器运行参数
  75. ```
  76. -h, --help show this help message and exit
  77. -s SEED, --seed=SEED the random seed
  78. -t NUMTHREADS, --threads=NUMTHREADS
  79. number of threads
  80. -p PROGFILE, --program=PROGFILE
  81. source program (in .s)
  82. -i INTFREQ, --interrupt=INTFREQ
  83. interrupt frequency
  84. -r, --randints if interrupts are random
  85. -a ARGV, --argv=ARGV comma-separated per-thread args (e.g., ax=1,ax=2 sets
  86. thread 0 ax reg to 1 and thread 1 ax reg to 2);
  87. specify multiple regs per thread via colon-separated
  88. list (e.g., ax=1:bx=2,cx=3 sets thread 0 ax and bx and
  89. just cx for thread 1)
  90. -L LOADADDR, --loadaddr=LOADADDR
  91. address where to load code
  92. -m MEMSIZE, --memsize=MEMSIZE
  93. size of address space (KB)
  94. -M MEMTRACE, --memtrace=MEMTRACE
  95. comma-separated list of addrs to trace (e.g.,
  96. 20000,20001)
  97. -R REGTRACE, --regtrace=REGTRACE
  98. comma-separated list of regs to trace (e.g.,
  99. ax,bx,cx,dx)
  100. -C, --cctrace should we trace condition codes
  101. -S, --printstats print some extra stats
  102. -v, --verbose print some extra info
  103. -c, --compute compute answers for me
  104. ```
  105. 执行举例
  106. ```
  107. $ ./x86.py -p simple-race.s -t 1 -M 2000 -R ax,bx
  108. 2000 ax bx Thread 0
  109. ? ? ?
  110. ? ? ? 1000 mov 2000, %ax
  111. ? ? ? 1001 add $1, %ax
  112. ? ? ? 1002 mov %ax, 2000
  113. ? ? ? 1003 halt
  114. ```
  115. 如果加上参数 `-c`可得到具体执行结果
  116. ```
  117. $ ./x86.py -p simple-race.s -t 1 -M 2000 -R ax,bx -c
  118. 2000 ax bx Thread 0
  119. 0 0 0
  120. 0 0 0 1000 mov 2000, %ax
  121. 0 1 0 1001 add $1, %ax
  122. 1 1 0 1002 mov %ax, 2000
  123. 1 1 0 1003 halt
  124. ```
  125. 另外一个执行的例子
  126. ```
  127. $ ./x86.py -p loop.s -t 1 -a dx=3 -R dx -C -c
  128. dx >= > <= < != == Thread 0
  129. 3 0 0 0 0 0 0
  130. 2 0 0 0 0 0 0 1000 sub $1,%dx
  131. 2 1 1 0 0 1 0 1001 test $0,%dx
  132. 2 1 1 0 0 1 0 1002 jgte .top
  133. 1 1 1 0 0 1 0 1000 sub $1,%dx
  134. 1 1 1 0 0 1 0 1001 test $0,%dx
  135. 1 1 1 0 0 1 0 1002 jgte .top
  136. 0 1 1 0 0 1 0 1000 sub $1,%dx
  137. 0 1 0 1 0 0 1 1001 test $0,%dx
  138. 0 1 0 1 0 0 1 1002 jgte .top
  139. 0 1 0 1 0 0 1 1003 halt
  140. ```
  141. 多线程存在race condition 的例子 looping-race-nolock.s
  142. ```
  143. .main
  144. .top
  145. # critical section
  146. mov 2000, %ax # get the value at the address
  147. add $1, %ax # increment it
  148. mov %ax, 2000 # store it back
  149. # see if we're still looping
  150. sub $1, %bx
  151. test $0, %bx
  152. jgt .top
  153. halt
  154. ```
  155. 执行结果:
  156. ```
  157. $ ./x86.py -p looping-race-nolock.s -t 2 -a bx=1 -M 2000 -c
  158. 2000 bx Thread 0 Thread 1
  159. 0 1
  160. 0 1 1000 mov 2000, %ax
  161. 0 1 1001 add $1, %ax
  162. 1 1 1002 mov %ax, 2000
  163. 1 0 1003 sub $1, %bx
  164. 1 0 1004 test $0, %bx
  165. 1 0 1005 jgt .top
  166. 1 0 1006 halt
  167. 1 1 ----- Halt;Switch ----- ----- Halt;Switch -----
  168. 1 1 1000 mov 2000, %ax
  169. 1 1 1001 add $1, %ax
  170. 2 1 1002 mov %ax, 2000
  171. 2 0 1003 sub $1, %bx
  172. 2 0 1004 test $0, %bx
  173. 2 0 1005 jgt .top
  174. 2 0 1006 halt
  175. ```
  176. 多线程存在 race condition 的例子 looping-race-nolock.s 在引入中断后,会产生race condition.
  177. ```
  178. $ ./x86.py -p looping-race-nolock.s -t 2 -a bx=1 -M 2000 -i 2
  179. 2000 Thread 0 Thread 1
  180. ?
  181. ? 1000 mov 2000, %ax
  182. ? 1001 add $1, %ax
  183. ? ------ Interrupt ------ ------ Interrupt ------
  184. ? 1000 mov 2000, %ax
  185. ? 1001 add $1, %ax
  186. ? ------ Interrupt ------ ------ Interrupt ------
  187. ? 1002 mov %ax, 2000
  188. ? 1003 sub $1, %bx
  189. ? ------ Interrupt ------ ------ Interrupt ------
  190. ? 1002 mov %ax, 2000
  191. ? 1003 sub $1, %bx
  192. ? ------ Interrupt ------ ------ Interrupt ------
  193. ? 1004 test $0, %bx
  194. ? 1005 jgt .top
  195. ? ------ Interrupt ------ ------ Interrupt ------
  196. ? 1004 test $0, %bx
  197. ? 1005 jgt .top
  198. ? ------ Interrupt ------ ------ Interrupt ------
  199. ? 1006 halt
  200. ? ----- Halt;Switch ----- ----- Halt;Switch -----
  201. ? 1006 halt
  202. ```