《操作系统》的实验代码。
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.

256 lines
7.7 KiB

12 years ago
12 years ago
  1. #include <stdio.h>
  2. #include <proc.h>
  3. #include <sem.h>
  4. #include <monitor.h>
  5. #include <assert.h>
  6. #define N 5 /* 哲学家数目 */
  7. #define LEFT (i-1+N)%N /* i的左邻号码 */
  8. #define RIGHT (i+1)%N /* i的右邻号码 */
  9. #define THINKING 0 /* 哲学家正在思考 */
  10. #define HUNGRY 1 /* 哲学家想取得叉子 */
  11. #define EATING 2 /* 哲学家正在吃面 */
  12. #define TIMES 4 /* 吃4次饭 */
  13. #define SLEEP_TIME 10
  14. //-----------------philosopher problem using monitor ------------
  15. /*PSEUDO CODE :philosopher problem using semaphore
  16. system DINING_PHILOSOPHERS
  17. VAR
  18. me: semaphore, initially 1; # for mutual exclusion
  19. s[5]: semaphore s[5], initially 0; # for synchronization
  20. pflag[5]: {THINK, HUNGRY, EAT}, initially THINK; # philosopher flag
  21. # As before, each philosopher is an endless cycle of thinking and eating.
  22. procedure philosopher(i)
  23. {
  24. while TRUE do
  25. {
  26. THINKING;
  27. take_chopsticks(i);
  28. EATING;
  29. drop_chopsticks(i);
  30. }
  31. }
  32. # The take_chopsticks procedure involves checking the status of neighboring
  33. # philosophers and then declaring one's own intention to eat. This is a two-phase
  34. # protocol; first declaring the status HUNGRY, then going on to EAT.
  35. procedure take_chopsticks(i)
  36. {
  37. DOWN(me); # critical section
  38. pflag[i] := HUNGRY;
  39. test[i];
  40. UP(me); # end critical section
  41. DOWN(s[i]) # Eat if enabled
  42. }
  43. void test(i) # Let phil[i] eat, if waiting
  44. {
  45. if ( pflag[i] == HUNGRY
  46. && pflag[i-1] != EAT
  47. && pflag[i+1] != EAT)
  48. then
  49. {
  50. pflag[i] := EAT;
  51. UP(s[i])
  52. }
  53. }
  54. # Once a philosopher finishes eating, all that remains is to relinquish the
  55. # resources---its two chopsticks---and thereby release waiting neighbors.
  56. void drop_chopsticks(int i)
  57. {
  58. DOWN(me); # critical section
  59. test(i-1); # Let phil. on left eat if possible
  60. test(i+1); # Let phil. on rght eat if possible
  61. UP(me); # up critical section
  62. }
  63. */
  64. //---------- philosophers problem using semaphore ----------------------
  65. int state_sema[N]; /* 记录每个人状态的数组 */
  66. /* 信号量是一个特殊的整型变量 */
  67. semaphore_t mutex; /* 临界区互斥 */
  68. semaphore_t s[N]; /* 每个哲学家一个信号量 */
  69. struct proc_struct *philosopher_proc_sema[N];
  70. void phi_test_sema(i) /* i:哲学家号码从0到N-1 */
  71. {
  72. if(state_sema[i]==HUNGRY&&state_sema[LEFT]!=EATING
  73. &&state_sema[RIGHT]!=EATING)
  74. {
  75. state_sema[i]=EATING;
  76. up(&s[i]);
  77. }
  78. }
  79. void phi_take_forks_sema(int i) /* i:哲学家号码从0到N-1 */
  80. {
  81. down(&mutex); /* 进入临界区 */
  82. state_sema[i]=HUNGRY; /* 记录下哲学家i饥饿的事实 */
  83. phi_test_sema(i); /* 试图得到两只叉子 */
  84. up(&mutex); /* 离开临界区 */
  85. down(&s[i]); /* 如果得不到叉子就阻塞 */
  86. }
  87. void phi_put_forks_sema(int i) /* i:哲学家号码从0到N-1 */
  88. {
  89. down(&mutex); /* 进入临界区 */
  90. state_sema[i]=THINKING; /* 哲学家进餐结束 */
  91. phi_test_sema(LEFT); /* 看一下左邻居现在是否能进餐 */
  92. phi_test_sema(RIGHT); /* 看一下右邻居现在是否能进餐 */
  93. up(&mutex); /* 离开临界区 */
  94. }
  95. int philosopher_using_semaphore(void * arg) /* i:哲学家号码,从0到N-1 */
  96. {
  97. int i, iter=0;
  98. i=(int)arg;
  99. cprintf("I am No.%d philosopher_sema\n",i);
  100. while(iter++<TIMES)
  101. { /* 无限循环 */
  102. cprintf("Iter %d, No.%d philosopher_sema is thinking\n",iter,i); /* 哲学家正在思考 */
  103. do_sleep(SLEEP_TIME);
  104. phi_take_forks_sema(i);
  105. /* 需要两只叉子,或者阻塞 */
  106. cprintf("Iter %d, No.%d philosopher_sema is eating\n",iter,i); /* 进餐 */
  107. do_sleep(SLEEP_TIME);
  108. phi_put_forks_sema(i);
  109. /* 把两把叉子同时放回桌子 */
  110. }
  111. cprintf("No.%d philosopher_sema quit\n",i);
  112. return 0;
  113. }
  114. //-----------------philosopher problem using monitor ------------
  115. /*PSEUDO CODE :philosopher problem using monitor
  116. * monitor dp
  117. * {
  118. * enum {thinking, hungry, eating} state[5];
  119. * condition self[5];
  120. *
  121. * void pickup(int i) {
  122. * state[i] = hungry;
  123. * if ((state[(i+4)%5] != eating) && (state[(i+1)%5] != eating)) {
  124. * state[i] = eating;
  125. * else
  126. * self[i].wait();
  127. * }
  128. *
  129. * void putdown(int i) {
  130. * state[i] = thinking;
  131. * if ((state[(i+4)%5] == hungry) && (state[(i+3)%5] != eating)) {
  132. * state[(i+4)%5] = eating;
  133. * self[(i+4)%5].signal();
  134. * }
  135. * if ((state[(i+1)%5] == hungry) && (state[(i+2)%5] != eating)) {
  136. * state[(i+1)%5] = eating;
  137. * self[(i+1)%5].signal();
  138. * }
  139. * }
  140. *
  141. * void init() {
  142. * for (int i = 0; i < 5; i++)
  143. * state[i] = thinking;
  144. * }
  145. * }
  146. */
  147. struct proc_struct *philosopher_proc_condvar[N]; // N philosopher
  148. int state_condvar[N]; // the philosopher's state: EATING, HUNGARY, THINKING
  149. monitor_t mt, *mtp=&mt; // monitor
  150. void phi_test_condvar (i) {
  151. if(state_condvar[i]==HUNGRY&&state_condvar[LEFT]!=EATING
  152. &&state_condvar[RIGHT]!=EATING) {
  153. cprintf("phi_test_condvar: state_condvar[%d] will eating\n",i);
  154. state_condvar[i] = EATING ;
  155. cprintf("phi_test_condvar: signal self_cv[%d] \n",i);
  156. cond_signal(&mtp->cv[i]) ;
  157. }
  158. }
  159. void phi_take_forks_condvar(int i) {
  160. down(&(mtp->mutex));
  161. //--------into routine in monitor--------------
  162. // LAB7 EXERCISE1: YOUR CODE
  163. // I am hungry
  164. // try to get fork
  165. //--------leave routine in monitor--------------
  166. if(mtp->next_count>0)
  167. up(&(mtp->next));
  168. else
  169. up(&(mtp->mutex));
  170. }
  171. void phi_put_forks_condvar(int i) {
  172. down(&(mtp->mutex));
  173. //--------into routine in monitor--------------
  174. // LAB7 EXERCISE1: YOUR CODE
  175. // I ate over
  176. // test left and right neighbors
  177. //--------leave routine in monitor--------------
  178. if(mtp->next_count>0)
  179. up(&(mtp->next));
  180. else
  181. up(&(mtp->mutex));
  182. }
  183. //---------- philosophers using monitor (condition variable) ----------------------
  184. int philosopher_using_condvar(void * arg) { /* arg is the No. of philosopher 0~N-1*/
  185. int i, iter=0;
  186. i=(int)arg;
  187. cprintf("I am No.%d philosopher_condvar\n",i);
  188. while(iter++<TIMES)
  189. { /* iterate*/
  190. cprintf("Iter %d, No.%d philosopher_condvar is thinking\n",iter,i); /* thinking*/
  191. do_sleep(SLEEP_TIME);
  192. phi_take_forks_condvar(i);
  193. /* need two forks, maybe blocked */
  194. cprintf("Iter %d, No.%d philosopher_condvar is eating\n",iter,i); /* eating*/
  195. do_sleep(SLEEP_TIME);
  196. phi_put_forks_condvar(i);
  197. /* return two forks back*/
  198. }
  199. cprintf("No.%d philosopher_condvar quit\n",i);
  200. return 0;
  201. }
  202. void check_sync(void){
  203. int i;
  204. //check semaphore
  205. sem_init(&mutex, 1);
  206. for(i=0;i<N;i++){
  207. sem_init(&s[i], 0);
  208. int pid = kernel_thread(philosopher_using_semaphore, (void *)i, 0);
  209. if (pid <= 0) {
  210. panic("create No.%d philosopher_using_semaphore failed.\n");
  211. }
  212. philosopher_proc_sema[i] = find_proc(pid);
  213. set_proc_name(philosopher_proc_sema[i], "philosopher_sema_proc");
  214. }
  215. //check condition variable
  216. monitor_init(&mt, N);
  217. for(i=0;i<N;i++){
  218. state_condvar[i]=THINKING;
  219. int pid = kernel_thread(philosopher_using_condvar, (void *)i, 0);
  220. if (pid <= 0) {
  221. panic("create No.%d philosopher_using_condvar failed.\n");
  222. }
  223. philosopher_proc_condvar[i] = find_proc(pid);
  224. set_proc_name(philosopher_proc_condvar[i], "philosopher_condvar_proc");
  225. }
  226. }