traffic_synch.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. #include <types.h>
  2. #include <lib.h>
  3. #include <synchprobs.h>
  4. #include <synch.h>
  5. #include <opt-A1.h>
  6. /*
  7. * This simple default synchronization mechanism allows only vehicle at a time
  8. * into the intersection. The intersectionSem is used as a a lock.
  9. * We use a semaphore rather than a lock so that this code will work even
  10. * before locks are implemented.
  11. */
  12. /*
  13. * Replace this default synchronization mechanism with your own (better) mechanism
  14. * needed for your solution. Your mechanism may use any of the available synchronzation
  15. * primitives, e.g., semaphores, locks, condition variables. You are also free to
  16. * declare other global variables if your solution requires them.
  17. */
  18. /*
  19. * replace this with declarations of any synchronization and other variables you need here
  20. */
  21. static struct lock * globlock;
  22. typedef struct cv cv;
  23. // This section contains global vars and useful functions to work with them. As well as the structs used for them
  24. typedef struct car
  25. {
  26. Direction origin;
  27. Direction dest;
  28. bool old;
  29. struct car * next;
  30. struct cv * cv;
  31. } car;
  32. typedef struct list
  33. {
  34. car * front;
  35. car * back;
  36. } list;
  37. list * active = NULL;
  38. // car initializer/allocator
  39. static car * newcar(Direction origin, Direction dest)
  40. {
  41. car * temp = kmalloc(sizeof(car));
  42. if(!(temp))
  43. {
  44. panic("Failed to create a car.");
  45. }
  46. temp->origin = origin;
  47. temp->dest = dest;
  48. temp->old = 0;
  49. temp->next = NULL;
  50. temp->cv = NULL;
  51. return temp;
  52. }
  53. // list initializer/allocator
  54. static list * newlist()
  55. {
  56. list * temp = kmalloc(sizeof(list));
  57. if(!(temp))
  58. {
  59. panic("Could not allocate list.");
  60. }
  61. temp->front = NULL;
  62. temp->back = NULL;
  63. return temp;
  64. }
  65. // push a car to the end of the active list
  66. static void push(car * newcar)
  67. {
  68. if (!(active->front))
  69. {
  70. active->front = newcar;
  71. active->back = newcar;
  72. return;
  73. }
  74. active->back->next = newcar;
  75. active->back = newcar;
  76. }
  77. // called when a car clears the intersection
  78. static void clearint(car * done)
  79. {
  80. car * temp = active->front;
  81. car * temp2 = NULL;
  82. while(temp != done)
  83. {
  84. temp2 = temp;
  85. temp = temp->next;
  86. }
  87. // first element of the list is being removed
  88. if (!(temp2))
  89. {
  90. active->front = active->front->next;
  91. goto SKIP1;
  92. }
  93. temp2->next = temp->next;
  94. SKIP1:
  95. if (temp->cv) // if this car was blocking something
  96. {
  97. lock_acquire(globlock);
  98. cv_broadcast(temp->cv, globlock); // wake all/inform them you're all good
  99. lock_release(globlock);
  100. kfree(temp->cv);
  101. }
  102. kfree(temp);
  103. }
  104. // cleans up a list
  105. static void dellist(list * dead)
  106. {
  107. car * temp = dead->front;
  108. while (temp)
  109. {
  110. car * temp2 = temp->next;
  111. kfree(temp->cv);
  112. kfree(temp);
  113. temp = temp2;
  114. }
  115. kfree(dead);
  116. }
  117. // returns true if a car is turning right
  118. static bool rightturn(car * car)
  119. {
  120. int temp = car->origin - car->dest;
  121. return (temp == 1 || temp == -3);
  122. }
  123. /*
  124. * The simulation driver will call this function once before starting
  125. * the simulation
  126. *
  127. * You can use it to initialize synchronization and other variables.
  128. *
  129. */
  130. void intersection_sync_init()
  131. {
  132. globlock = lock_create("lightlock");
  133. if (!(globlock))
  134. {
  135. panic("Failed to create lock!");
  136. }
  137. active = newlist();
  138. }
  139. /*
  140. * The simulation driver will call this function once after
  141. * the simulation has finished
  142. *
  143. * You can use it to clean up any synchronization and other variables.
  144. *
  145. */
  146. void intersection_sync_cleanup()
  147. {
  148. KASSERT(active);
  149. dellist(active);
  150. lock_destroy(globlock);
  151. }
  152. /*
  153. * The simulation driver will call this function each time a vehicle
  154. * tries to enter the intersection, before it enters.
  155. * This function should cause the calling simulation thread
  156. * to block until it is OK for the vehicle to enter the intersection.
  157. *
  158. * parameters:
  159. * * origin: the Direction from which the vehicle is arriving
  160. * * destination: the Direction in which the vehicle is trying to go
  161. *
  162. * return value: none
  163. */
  164. void intersection_before_entry(Direction origin, Direction destination)
  165. {
  166. lock_acquire(globlock);
  167. car * new = newcar(origin, destination);
  168. RESTART:
  169. // Nothing in intersection, so proceed
  170. if (!(active->front))
  171. {
  172. push(new);
  173. lock_release(globlock);
  174. return;
  175. }
  176. else // things are in the intersection
  177. {
  178. car * temp = active->front;
  179. while (temp)
  180. {
  181. if (temp->origin == new->origin || (temp->origin == new->dest && temp->dest == new->origin) || (temp->dest != new->dest && (rightturn(new) || rightturn(temp))))
  182. {
  183. temp = temp->next;
  184. continue;
  185. }
  186. else
  187. {
  188. new->old = 1; // make new "old", since now it has already waited once
  189. // create cv for temp if it doesn't have one yet
  190. if(!(temp->cv))
  191. {
  192. temp->cv = cv_create("carcv");
  193. }
  194. cv_wait(temp->cv, globlock); // sleep and reacquire lock once woken
  195. goto RESTART; // now we have to make sure there's nothing else screwing us over
  196. }
  197. }
  198. push(new);
  199. lock_release(globlock);
  200. }
  201. }
  202. /*
  203. * The simulation driver will call this function each time a vehicle
  204. * leaves the intersection.
  205. *
  206. * parameters:
  207. * * origin: the Direction from which the vehicle arrived
  208. * * destination: the Direction in which the vehicle is going
  209. *
  210. * return value: none
  211. */
  212. void intersection_after_exit(Direction origin, Direction destination)
  213. {
  214. car * temp = active->front;
  215. while (temp)
  216. {
  217. if (temp->origin == origin && temp->dest == destination)
  218. {
  219. clearint(temp);
  220. break;
  221. }
  222. else
  223. {
  224. temp = temp->next;
  225. }
  226. }
  227. }