traffic_synch.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  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. car * next;
  30. cv * cv;
  31. } car;
  32. typedef struct list
  33. {
  34. car * front;
  35. car * back;
  36. } list;
  37. list * queue = NULL;
  38. list * active = NULL;
  39. // car initializer/allocator
  40. struct car * newcar(Direction origin, Direction dest)
  41. {
  42. car * temp = kmalloc(sizeof(car));
  43. if(!(temp))
  44. {
  45. panic("Failed to create a car.");
  46. }
  47. temp->origin = origin;
  48. temp->dest = dest;
  49. temp->old = 0;
  50. temp->next = NULL;
  51. temp->cv = NULL;
  52. }
  53. // list initializer/allocator
  54. struct 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. }
  64. // puts a car into the queue, at the front if old is true, the back otherwise
  65. void enqueue(car * newcar)
  66. {
  67. if (!(queue->back))
  68. {
  69. queue->front = newcar;
  70. queue->back = newcar;
  71. }
  72. if (newcar->old) // if the car is "old", let it go first. be nice to your elders
  73. {
  74. car * temp = queue->front;
  75. queue->front = newcar;
  76. newcar->next = temp;
  77. return;
  78. }
  79. queue->back->next = newcar;
  80. queue->back = newcar;
  81. }
  82. // push a car to the end of the active list
  83. void push(car * newcar)
  84. {
  85. if (!(active->front))
  86. {
  87. active->front = newcar;
  88. active->back = newcar;
  89. }
  90. active->back->next = newcar;
  91. active->back = newcar;
  92. }
  93. // remove an element from the front of the queue
  94. struct car * pop()
  95. {
  96. if (!(queue->front))
  97. {
  98. return NULL;
  99. }
  100. if (queue->front == queue->back)
  101. {
  102. queue->back == NULL;
  103. }
  104. car * temp = queue->front;
  105. queue->front = queue->front->next;
  106. return temp;
  107. }
  108. // called when a car clears the intersection
  109. void clearint(car * done)
  110. {
  111. car * temp = active->front;
  112. car * temp2 = NULL;
  113. while(temp != done)
  114. {
  115. temp2 = temp;
  116. temp = temp>next;
  117. }
  118. // first element of the list is being removed
  119. if (!(temp2))
  120. {
  121. active->front = active->front->next;
  122. goto SKIP1;
  123. }
  124. temp2->next = temp->next;
  125. SKIP1:
  126. if (temp->cv) // if this car was blocking something
  127. {
  128. cv_broadcast(temp->cv, globlock); // wake all/inform them you're all good
  129. kfree(temp->cv);
  130. }
  131. kfree(temp);
  132. }
  133. // cleans up a list
  134. void dellist(list * dead)
  135. {
  136. car * temp = dead->front;
  137. while (temp)
  138. {
  139. car * temp2 = temp->next;
  140. kfree(temp->cv);
  141. kfree(temp);
  142. temp = temp2;
  143. }
  144. kfree(dead);
  145. }
  146. // returns true if a car is turning right
  147. bool rightturn(car * car)
  148. {
  149. int temp = car->origin - car->dest;
  150. return (temp == 1 || temp == -3);
  151. }
  152. /*
  153. * The simulation driver will call this function once before starting
  154. * the simulation
  155. *
  156. * You can use it to initialize synchronization and other variables.
  157. *
  158. */
  159. void intersection_sync_init()
  160. {
  161. globlock = lock_create("lightlock");
  162. if (!(globlock))
  163. {
  164. panic("Failed to create lock!");
  165. }
  166. queue = newlist();
  167. active = newlist();
  168. }
  169. /*
  170. * The simulation driver will call this function once after
  171. * the simulation has finished
  172. *
  173. * You can use it to clean up any synchronization and other variables.
  174. *
  175. */
  176. void intersection_sync_cleanup()
  177. {
  178. KASSERT(queue);
  179. KASSERT(active);
  180. dellist(queue);
  181. dellist(active);
  182. lock_destroy(globlock);
  183. }
  184. /*
  185. * The simulation driver will call this function each time a vehicle
  186. * tries to enter the intersection, before it enters.
  187. * This function should cause the calling simulation thread
  188. * to block until it is OK for the vehicle to enter the intersection.
  189. *
  190. * parameters:
  191. * * origin: the Direction from which the vehicle is arriving
  192. * * destination: the Direction in which the vehicle is trying to go
  193. *
  194. * return value: none
  195. */
  196. void intersection_before_entry(Direction origin, Direction destination)
  197. {
  198. lock_acquire(globlock);
  199. car * new = newcar(origin, destination);
  200. RESTART:
  201. // Nothing in intersection, so proceed
  202. if (!(active->front))
  203. {
  204. push(new);
  205. lock_release(globlock);
  206. return;
  207. }
  208. else // things are in the intersection
  209. {
  210. car * temp = active->front;
  211. while (temp)
  212. {
  213. if (temp->origin == new->origin || (temp->origin == new->dest && temp->dest == new->origin) || (temp->dest != new->dest && (rightturn(new) || rightturn(temp))))
  214. {
  215. temp = temp->next;
  216. continue;
  217. }
  218. else
  219. {
  220. enqueue(new);
  221. new->old = 1; // make new "old", since now it has already waited once
  222. lock_release(globlock);
  223. // create cv for temp if it doesn't have one yet
  224. if(!(temp->cv))
  225. {
  226. temp->cv = cv_create("carcv");
  227. }
  228. cv_wait(temp->cv, globlock); // sleep and reacquire lock once woken
  229. goto RESTART; // now we have to make sure there's nothing else screwing us over
  230. }
  231. }
  232. push(new);
  233. lock_release(globlock);
  234. }
  235. }
  236. /*
  237. * The simulation driver will call this function each time a vehicle
  238. * leaves the intersection.
  239. *
  240. * parameters:
  241. * * origin: the Direction from which the vehicle arrived
  242. * * destination: the Direction in which the vehicle is going
  243. *
  244. * return value: none
  245. */
  246. void intersection_after_exit(Direction origin, Direction destination)
  247. {
  248. car * temp = active->front;
  249. while (temp)
  250. {
  251. if (temp->origin == origin && temp->dest == destination)
  252. {
  253. clearint(temp);
  254. break;
  255. }
  256. else
  257. {
  258. temp = temp->next;
  259. }
  260. }
  261. }